<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          彈簧秤稱球問(wèn)題算法分析及程序模擬

          共 5125字,需瀏覽 11分鐘

           ·

          2022-05-30 09:40

          一、拋出問(wèn)題

          ???????? 昨天紹興越州中學(xué)趙軍老師在QQ群里發(fā)了一個(gè)有趣的問(wèn)題,引起了眾多老師的熱烈討論。問(wèn)題如下:
          6只球外觀完全一樣,但5球重量一樣,僅有一只重量不同,不知是輕還是重。問(wèn):使用一只彈簧稱,其可以稱出任意多個(gè)球的重量,最多稱重三次,如何求出每個(gè)球重量?

          一開(kāi)始大家都以為是傳統(tǒng)的無(wú)砝碼天平稱球問(wèn)題,想用分治算法來(lái)解決。在趙軍老師的提示之后,才發(fā)現(xiàn)彈簧秤和無(wú)砝碼天平的區(qū)別:彈簧秤是可以稱量出小球的具體重量的,而且題目要求求出每個(gè)球的具體重量。

          我看了一下題目和大家的討論,一時(shí)半會(huì)也想不出什么辦法來(lái),就備課去了。
          二、驚現(xiàn)妙解
          過(guò)了一會(huì)兒,發(fā)現(xiàn)QQ群里又多了不少消息,其中桐鄉(xiāng)高級(jí)中學(xué)朱海寧老師的發(fā)言引起了我的注意。

          朱老師把小球依次編號(hào)1-6,分成3次稱量,第一次將球1,2,3合在一起稱,第二次將球2,3,4,5合在一起稱,第三次將球3,4合在一起稱,可以表示為:3x=123,4y=2345,2z=34

          ?一開(kāi)始我沒(méi)怎么看懂,發(fā)現(xiàn)朱老師提供的表達(dá)式中沒(méi)有出現(xiàn)6號(hào)球,心里就產(chǎn)生了疑問(wèn),萬(wàn)一6號(hào)球是異球呢?不稱量它怎么得出異球的重量?于是隨口說(shuō)了一句:@桐鄉(xiāng)高級(jí)中學(xué)朱海寧?6個(gè)球哦。

          朱老師耐心地回答我:可以推出來(lái)的,比如x=y,那就是6號(hào)球有問(wèn)題,單獨(dú)稱一下就好。

          聽(tīng)了這句話,我感覺(jué)有點(diǎn)明白了,其實(shí)第三次稱量不一定是將球3,4合在一起稱。若前兩次稱量結(jié)果證明了x=y,則說(shuō)明6號(hào)球是異球,那么第三次就直接稱量6號(hào)球,再根據(jù)前兩次稱量結(jié)果,可以計(jì)算出其他球的重量。

          我又繼續(xù)思考了x!=y的情形,發(fā)現(xiàn)可以輕松地推導(dǎo)出異球?yàn)?/span>15的情形,即當(dāng)y=z時(shí),異球?yàn)?/span>1;當(dāng)x=z時(shí),則異球?yàn)?/span>5

          但如果異球不是15呢?用純數(shù)學(xué)推導(dǎo)的方法似乎難以實(shí)現(xiàn)。我一下子又沒(méi)有思路了。
          三、靈光一現(xiàn)
          突然我靈光一現(xiàn)——為什么一定要采用數(shù)學(xué)推導(dǎo)的方式呢?計(jì)算思維,利用計(jì)算機(jī)來(lái)幫忙解決問(wèn)題,不正是我們信息技術(shù)學(xué)科的核心素養(yǎng)嗎?
          模擬算法是最容易想到的方法,給定一些測(cè)試數(shù)據(jù)去模擬計(jì)算結(jié)果。本問(wèn)題只有6個(gè)小球,問(wèn)題規(guī)模并不大,我們沒(méi)有必要直接編程解題,可以先在腦海中模擬一下。
          我先假設(shè)2號(hào)球是異球且偏輕,假設(shè)普通球的重量均為3,可設(shè)置2號(hào)球的重量為2,這樣就能計(jì)算出x = 8/3,y = 11/4z = 6/2,從而得到關(guān)系式x < y < z。
          同理,若3號(hào)球是異球且偏輕,則有z < x < y;若4號(hào)球是異球且偏輕,則有z < y < x
          由此我們就得出了當(dāng)異球偏輕時(shí)的各種可能性,而且可以根據(jù)xy,z的值計(jì)算出所有小球的重量。
          當(dāng)異球偏重時(shí)可以采用同樣的辦法解決,無(wú)非是不等號(hào)的方向變化了而已。
          四、算法梳理
          ???????? 現(xiàn)在我們來(lái)把整個(gè)算法梳理一下:
          1.先取出任意3個(gè)球(編號(hào)1,2,3)一起稱,得到表達(dá)式3x=123;
          2.從已稱量的3個(gè)球中任意拿出2個(gè)(假設(shè)是2,3,屬于A組),再?gòu)奈捶Q量的球中任意拿出2個(gè)(編號(hào)4,5,屬于B組),合在一起稱,得到表達(dá)式4y=2345;
          3.若x==y,則說(shuō)明球6為異球,稱量球6;
          4.若x!=y,則從A組拿出任意一個(gè)球(假設(shè)是3),從B組拿出任意一個(gè)球(假設(shè)是4),合在一起稱,得到表達(dá)式2z=34;
          5.根據(jù)x,y,z的大小關(guān)系,可以得知異球:若y=z,則說(shuō)明異球在x中,且異球?yàn)?/span>1;若x=z,則說(shuō)明異球在y中,且異球?yàn)?/span>5。
          其他情況可以將數(shù)據(jù)代入進(jìn)一步計(jì)算和推導(dǎo)。
          當(dāng)異球偏輕時(shí):若x,則異球?yàn)?/span>1;若x,則異球?yàn)?/span>2;若z,則異球?yàn)?/span>3;若z,則異球?yàn)?/span>4;若y,則異球?yàn)?/span>5。
          當(dāng)異球偏重時(shí):若x>y=z,則異球?yàn)?/span>1;若x>y>z,則異球?yàn)?/span>2;若z>x>y,則異球?yàn)?/span>3;若z>y>x,則異球?yàn)?/span>4;若y>x=z,則異球?yàn)?/span>5。
          當(dāng)然,第三次稱量的兩個(gè)球也不一定非得是34,只要保證從A,B組中各取一個(gè)就行了。其組合可以是24、25、3435。
          我把上述算法梳理發(fā)到了QQ群里,獲得了老師們的認(rèn)可,趙老師和朱老師都為我點(diǎn)贊。

          ?

          五、程序模擬

          事情到這里似乎已經(jīng)結(jié)束了。但只提出算法,不編寫(xiě)程序不是我的風(fēng)格。不把事情完全做好我是不會(huì)罷休的。于是我決定編寫(xiě)程序?qū)崿F(xiàn)算法功能。

          這是我的第一版程序:

          def fun_1(a):    x = sum(a[:3])  # 第一次稱重:3x=123    y = sum(a[1:5]) # 第二次稱重:4y=2345    if x/3 == y/4: # 前面5個(gè)球等重,則球6為異球        z = a[5] # 第三次稱重:稱量異球6        print(f"異球?yàn)?,其重量為{z},其他球重量為{x//3}")    else:        z = a[2] + a[3] # 第三次稱重:2z=34        if y/4 == z/2: # 異球?yàn)?            print(f"異球?yàn)?,其重量為{x-z},其他球重量為{z//2}")        elif x/3 == z/2: # 異球?yàn)?            print(f"異球?yàn)?,其重量為{y-x},其他球重量為{z//2}")        elif x/3 < y/4 < z/2 or x/3 > y/4 > z/2: # 異球?yàn)?            print(f"異球?yàn)?,其重量為{y-3*z//2},其他球重量為{z//2}")        elif z/2 < y/4 < x/3 or z/2 > y/4 > x/3: # 異球?yàn)?            print(f"異球?yàn)?,其重量為{z-x//3},其他球重量為{x//3}")        else: # 異球?yàn)?            print(f"異球?yàn)?,其重量為{2*z-x},其他球重量為{x-z}")import random       for i in range(16):    a = [3] * 6 # 初始化每個(gè)小球重量均為3    num = random.randint(0, 5) # 選擇任意一個(gè)小球?yàn)楫惽?/span>    a[num] = a[num] + random.choice([-1,1]) #異球重量可輕可重    print(a)????fun_1(a,?2,?4)
          ???????? 程序完全按照前面的算法來(lái)編寫(xiě),自認(rèn)為應(yīng)該是完美無(wú)缺的。但是程序運(yùn)行結(jié)果卻讓我傻了眼——第一個(gè)數(shù)據(jù)就錯(cuò)了,明明是4號(hào)球偏輕,程序卻說(shuō)異球?yàn)?/span>2,而且各個(gè)球的重量都算錯(cuò)了。

          我增加循環(huán)次數(shù),又測(cè)了好幾次,發(fā)現(xiàn)其他小球?yàn)楫惽驎r(shí)都是對(duì)的,就是4號(hào)球出錯(cuò)。

          問(wèn)題出在哪里呢?
          我陷入了沉思中。
          六、找出BUG

          為什么4號(hào)球總是出錯(cuò)呢?我又看了看測(cè)試結(jié)果,發(fā)現(xiàn)程序總是把4號(hào)球錯(cuò)認(rèn)為2號(hào)球。

          這說(shuō)明什么問(wèn)題呢?

          會(huì)不會(huì)是因?yàn)橄扰袛?/span>2號(hào)球,再判斷4號(hào)球的緣故?我嘗試著把多分支語(yǔ)句中elif語(yǔ)句的位置換了一下,讓程序先判斷4號(hào)球,再判斷2號(hào)球。

          再次運(yùn)行程序,觀看測(cè)試結(jié)果。果然不出所料,現(xiàn)在程序把2號(hào)球錯(cuò)認(rèn)為是4號(hào)球了。
          原來(lái)問(wèn)題出在這里!
          再仔細(xì)看看代碼,發(fā)現(xiàn)這兩條elif語(yǔ)句竟然是等效的,僅僅是寫(xiě)法變了一下而已!

          原來(lái)問(wèn)題出在這里!

          那該怎么修改呢?看上去似乎沒(méi)有辦法。難道我的算法本身就是錯(cuò)的?
          我再一次陷入了沉思。
          七、問(wèn)題解決

          2號(hào)球和4號(hào)球到底誰(shuí)才是異球?條件表達(dá)式怎么會(huì)一模一樣呢?是我漏掉了什么東西嗎?

          再仔細(xì)看看算法分析。咦,我好像發(fā)現(xiàn)了點(diǎn)什么。

          當(dāng)異球?yàn)?/span>2時(shí),4號(hào)球是普通球,則z應(yīng)該為整數(shù);同理,當(dāng)異球?yàn)?/span>4時(shí),2號(hào)球是普通球,則x應(yīng)該為整數(shù)。

          妙??!這是屬于我的尤里卡時(shí)刻!

          好了,現(xiàn)在只需要加上兩個(gè)限制條件就行了,第二版程序如下:

          def fun_2(a):    x = sum(a[:3])  # 第一次稱重:3x=123    y = sum(a[1:5]) # 第二次稱重:4y=2345    if x/3 == y/4: # 前面5個(gè)球等重,則球6為異球        z = a[5] # 第三次稱重:稱量異球6        print(f"異球?yàn)?,其重量為{z},其他球重量為{x//3}")    else:        z = a[2] + a[3] # 第三次稱重:2z=34        if y/4 == z/2: # 異球?yàn)?            print(f"異球?yàn)?,其重量為{x-z},其他球重量為{z//2}")        elif x/3 == z/2: # 異球?yàn)?            print(f"異球?yàn)?,其重量為{y-x},其他球重量為{z//2}")        elif z/2 == z//2 and (x/3 < y/4 < z/2 or x/3 > y/4 > z/2): # 異球?yàn)?            print(f"異球?yàn)?,其重量為{y-3*z//2},其他球重量為{z//2}")        elif x/3 == x//3 and (z/2 < y/4 < x/3 or z/2 > y/4 > x/3): # 異球?yàn)?            print(f"異球?yàn)?,其重量為{z-x//3},其他球重量為{x//3}")        else: # 異球?yàn)?            print(f"異球?yàn)?,其重量為{2*z-x},其他球重量為{x-z}")
          運(yùn)行程序,測(cè)試結(jié)果完美無(wú)瑕。

          ?

          八、精益求精

          現(xiàn)在,問(wèn)題應(yīng)該說(shuō)得到完美解決了。但解決問(wèn)題從來(lái)都沒(méi)有最好,只有更好。

          第三次稱量的方式有4種,我只考慮了其中一種。另外3種的結(jié)果是不是和前面一致?我還沒(méi)有編程驗(yàn)證。這件事情不做好,就不算完。

          于是,秉著精益求精的精神,追求完美的我又給出了第三版程序:

          def fun_3(a, i, j):    x = sum(a[:3])  # 第一次稱重:3x=123    y = sum(a[1:5]) # 第二次稱重:4y=2345    if x/3 == y/4: # 前面5個(gè)球等重,則球6為異球        z = a[5] # 第三次稱重:稱量異球6        print(f"異球?yàn)?,其重量為{z},其他球重量為{x//3}")    else:        z = a[i-1] + a[j-1] # 第三次稱重:2z=24或25或34或35        if y/4 == z/2: # 異球?yàn)?            print(f"異球?yàn)?,其重量為{x-z},其他球重量為{z//2}")        elif x/3 == z/2: # 異球?yàn)?-j            print(f"異球?yàn)?span id="go7utgvlrp"    class="code-snippet__subst">{9-j},其重量為{y-x},其他球重量為{z//2}")        elif z/2 == z//2 and (x/3 < y/4 < z/2 or x/3 > y/4 > z/2): # 異球?yàn)?-i            print(f"異球?yàn)?span id="go7utgvlrp"    class="code-snippet__subst">{5-i},其重量為{y-3*z//2},其他球重量為{z//2}")        elif x/3 == x//3 and (z/2 < y/4 < x/3 or z/2 > y/4 > x/3): # 異球?yàn)閖            print(f"異球?yàn)?span id="go7utgvlrp"    class="code-snippet__subst">{j},其重量為{z-x//3},其他球重量為{x//3}")        else: # 異球?yàn)閕            print(f"異球?yàn)?span id="go7utgvlrp"    class="code-snippet__subst">{i},其重量為{2*z-x},其他球重量為{x-z}")
          import random for i in range(16): a = [3] * 6 # 初始化每個(gè)小球重量均為3 num = random.randint(0, 5) # 選擇任意一個(gè)小球?yàn)楫惽?/span> a[num] = a[num] + random.choice([-1,1]) #異球重量可輕可重 print(a) fun_3(a, 2, 4) fun_3(a, 2, 5) fun_3(a, 3, 4) fun_3(a, 3, 5) print("#" * 20)
          程序運(yùn)行結(jié)果如下:

          終于搞定了,又可以愉快地玩耍上課了。


          需要本文源代碼和word文檔的,可以加入“Python算法之旅”知識(shí)星球參與討論和下載文件,Python算法之旅”知識(shí)星球匯集了數(shù)量眾多的同好,更多有趣的話題在這里討論,更多有用的資料在這里分享。

          我們專注Python算法,感興趣就一起來(lái)!

          相關(guān)優(yōu)秀文章:

          閱讀代碼和寫(xiě)更好的代碼

          最有效的學(xué)習(xí)方式

          Python算法之旅文章分類(lèi)

          瀏覽 140
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  性爱视频免费网站 | 免费一级全黄少妇性色生活片 | 欧美亚洲天堂网 | 中文天堂视频在线 | 欧美成人黄色电影网站 |