大家應該都聽說過這個老題目:有 1000 個一模一樣的瓶子,其中有 999 瓶是普通的水,有一瓶是毒葯。任何喝下毒葯的生物都會在一星期之后死亡。現在,你只有 10 只小白鼠和一星期的時間,如何檢驗出哪個瓶子里有毒葯?
這個問題的答案也堪稱經典:把瓶子從 0 到 999 依次編號,然后全部轉換為 10 位二進制數。讓第一只老鼠喝掉1到1000所有二進制數右起第一位是 1 的瓶子,讓第二只老鼠喝掉所有二進制數右起第二位是 1 的瓶子,等等。一星期后,如果第一只老鼠死了,就知道毒葯瓶子的二進制編號中,右起第一位是 1 ;如果第二只老鼠沒死,就知道毒葯瓶子的二進制編號中,右起第二位是 0 ……每只老鼠的死活都能確定出 10 位二進制數的其中一位,由此便可知道毒葯瓶子的編號了。
現在,有意思的問題來了:
這個問題的答案也堪稱經典:把瓶子從 0 到 999 依次編號,然后全部轉換為 10 位二進制數。讓第一只老鼠喝掉1到1000所有二進制數右起第一位是 1 的瓶子,讓第二只老鼠喝掉所有二進制數右起第二位是 1 的瓶子,等等。一星期后,如果第一只老鼠死了,就知道毒葯瓶子的二進制編號中,右起第一位是 1 ;如果第二只老鼠沒死,就知道毒葯瓶子的二進制編號中,右起第二位是 0 ……每只老鼠的死活都能確定出 10 位二進制數的其中一位,由此便可知道毒葯瓶子的編號了。
現在,有意思的問題來了:
1、如果你有兩個星期的時間(換句話說你可以做兩輪實驗),為了從 1000 個瓶子中找出毒葯,你最少需要幾只老鼠?注意,在第一輪實驗中死掉的老鼠,就無法繼續參與第二次實驗了。
答案:7 只老鼠就足夠了。事實上,7 只老鼠足以從 3^7 = 2187 個瓶子中找出毒葯來。首先,把所有瓶子從 0 到 2186 編號,然后全部轉換為 7 位三進制數。現在,讓第一只老鼠喝掉所有三進制數右起第一位是 2 的瓶子,讓第二只老鼠喝掉所有三進制數右起第二位是 2 的瓶子,等等。一星期之后,如果第一只老鼠死了,就知道毒葯瓶子的三進制編號中,右起第一位是 2 ;如果第二只老鼠沒死,就知道毒葯瓶子的三進制編號中,右起第二位不是 2,只可能是 0 或者 1 ……也就是說,每只死掉的老鼠都用自己的生命確定出了,三進制編號中自己負責的那一位是 2 ;但每只活着的老鼠都只能確定,它所負責的那一位不是 2 。於是,問題就歸約到了只剩一個星期時的情況。在第二輪實驗里,讓每只活着的老鼠繼續自己未完成的任務,喝掉它負責的那一位是 1 的所有瓶子。再過一星期,毒葯瓶子的三進制編號便能全部揭曉了。
類似地,我們可以證明, n 只小白鼠 t 周的時間可以從 (t+1)^n 個瓶子中檢驗出毒葯來。
2、有700瓶水,一瓶有毒,小白鼠喝一點點,20小時內死翹翹,那么至少用多少只小白鼠一定可以在50小時內找到哪瓶水有毒?
先看一個比這題簡單點的題目:如果只給你20小時找出那瓶有毒的葯水,該用多少只老鼠?
分析:20小時只能做一輪實驗。一只老鼠在喝了任意一瓶葯水后的狀態只可能有兩種:死or沒死,顯然,死=喝了毒葯,沒死=沒喝毒葯。按照信息論,一只小白鼠做一次實驗的信息量為I1=log2(2)=1bit,而700瓶葯水中找到一瓶毒葯所需之信息量為I2=log2(700),故需要的小白鼠數量為I2/I1=log2(700),向上取整后為10,即理論上至少需要10只小白鼠。但具體怎么找出這一瓶毒葯呢?
算法:將10只小白鼠排成一列,每一只相當於二進制數的一位,其中可設0=沒死=沒喝毒葯,1=死了=喝了毒葯。10只小白鼠可以表示的狀態數為2^10=1024>700,所以足夠了。將700個瓶子按照二進制依次編號,按照其編號,將對應位為1的瓶子里的葯水給表示對應位的小白鼠喝。比如6號瓶的二進制編碼為110,故從右到左第1位小白鼠不喝,而第2、3位小白鼠都要喝一口。如果20小時以后,第1位小白鼠木有掛,而第2、3位小白鼠掛了,說明毒葯的編號就是110,即6號瓶。
回到原題,原題與上題的區別在於50個小時,可以做兩輪實驗。當然,如果第一輪實驗就掛掉的小白鼠是無法做第二輪實驗的,但這無妨,可以用同樣的方法解決。理論上,一只小白鼠做兩輪實驗,可能有三種狀態:第一輪就掛了、第一輪木有掛而第二輪掛了、從頭到尾都木有掛。所以,一只小白鼠做兩輪實驗的信息量為I1=log2(3),而700瓶中找出一瓶毒葯所需之信息量仍然是I2=log2(700),故所需小白鼠為I2/I1=log3(700),向上取整為6只小白鼠。
至於具體的算法也是一樣的,只是這次所用的編碼為3進制,我們可以設0=從頭到尾都沒死,1=第一輪沒死第二輪死了,2=第一輪就死了。將對應位為2的瓶子給對應位的小白鼠喝。20小時后,如果有小白鼠死了,則可確定毒葯瓶子的編號某些位為2,而剩下的位可能是1,也可能是0,於是第二輪實驗便是上題一樣的二進制了,可以將對應位為2的瓶子全部留下,再重新編號做實驗。理論上剩下的小白鼠的數量足以完成實驗。
答案:7 只老鼠就足夠了。事實上,7 只老鼠足以從 3^7 = 2187 個瓶子中找出毒葯來。首先,把所有瓶子從 0 到 2186 編號,然后全部轉換為 7 位三進制數。現在,讓第一只老鼠喝掉所有三進制數右起第一位是 2 的瓶子,讓第二只老鼠喝掉所有三進制數右起第二位是 2 的瓶子,等等。一星期之后,如果第一只老鼠死了,就知道毒葯瓶子的三進制編號中,右起第一位是 2 ;如果第二只老鼠沒死,就知道毒葯瓶子的三進制編號中,右起第二位不是 2,只可能是 0 或者 1 ……也就是說,每只死掉的老鼠都用自己的生命確定出了,三進制編號中自己負責的那一位是 2 ;但每只活着的老鼠都只能確定,它所負責的那一位不是 2 。於是,問題就歸約到了只剩一個星期時的情況。在第二輪實驗里,讓每只活着的老鼠繼續自己未完成的任務,喝掉它負責的那一位是 1 的所有瓶子。再過一星期,毒葯瓶子的三進制編號便能全部揭曉了。
類似地,我們可以證明, n 只小白鼠 t 周的時間可以從 (t+1)^n 個瓶子中檢驗出毒葯來。
2、有700瓶水,一瓶有毒,小白鼠喝一點點,20小時內死翹翹,那么至少用多少只小白鼠一定可以在50小時內找到哪瓶水有毒?
先看一個比這題簡單點的題目:如果只給你20小時找出那瓶有毒的葯水,該用多少只老鼠?
分析:20小時只能做一輪實驗。一只老鼠在喝了任意一瓶葯水后的狀態只可能有兩種:死or沒死,顯然,死=喝了毒葯,沒死=沒喝毒葯。按照信息論,一只小白鼠做一次實驗的信息量為I1=log2(2)=1bit,而700瓶葯水中找到一瓶毒葯所需之信息量為I2=log2(700),故需要的小白鼠數量為I2/I1=log2(700),向上取整后為10,即理論上至少需要10只小白鼠。但具體怎么找出這一瓶毒葯呢?
算法:將10只小白鼠排成一列,每一只相當於二進制數的一位,其中可設0=沒死=沒喝毒葯,1=死了=喝了毒葯。10只小白鼠可以表示的狀態數為2^10=1024>700,所以足夠了。將700個瓶子按照二進制依次編號,按照其編號,將對應位為1的瓶子里的葯水給表示對應位的小白鼠喝。比如6號瓶的二進制編碼為110,故從右到左第1位小白鼠不喝,而第2、3位小白鼠都要喝一口。如果20小時以后,第1位小白鼠木有掛,而第2、3位小白鼠掛了,說明毒葯的編號就是110,即6號瓶。
回到原題,原題與上題的區別在於50個小時,可以做兩輪實驗。當然,如果第一輪實驗就掛掉的小白鼠是無法做第二輪實驗的,但這無妨,可以用同樣的方法解決。理論上,一只小白鼠做兩輪實驗,可能有三種狀態:第一輪就掛了、第一輪木有掛而第二輪掛了、從頭到尾都木有掛。所以,一只小白鼠做兩輪實驗的信息量為I1=log2(3),而700瓶中找出一瓶毒葯所需之信息量仍然是I2=log2(700),故所需小白鼠為I2/I1=log3(700),向上取整為6只小白鼠。
至於具體的算法也是一樣的,只是這次所用的編碼為3進制,我們可以設0=從頭到尾都沒死,1=第一輪沒死第二輪死了,2=第一輪就死了。將對應位為2的瓶子給對應位的小白鼠喝。20小時后,如果有小白鼠死了,則可確定毒葯瓶子的編號某些位為2,而剩下的位可能是1,也可能是0,於是第二輪實驗便是上題一樣的二進制了,可以將對應位為2的瓶子全部留下,再重新編號做實驗。理論上剩下的小白鼠的數量足以完成實驗。