動態規劃法(六)雞蛋掉落問題(一)(egg dropping problem)
繼續講故事~~
這天,丁丁正走在路上,欣賞著路邊迷人的城市風景,突然發現前面的大樓前圍了一波吃瓜群眾。他好奇地湊上前去,想一探究竟,看看到底發生了什麼事情。
原來本市的一位小有名氣的科學家正在這幢大樓進行一個實驗:某種材料的防護效能。他在大樓的底下鋪了一層這種防護材料,想拿雞蛋做實驗,將雞蛋從樓層掉下,看看雞蛋從哪一層掉下去會摔碎,以此測試該材料的防護效能。這就是著名的雞蛋掉落問題(egg dropping problem),即給定N個雞蛋和k層樓,試問至少需要幾次才能確定雞蛋從哪一層樓掉下去恰好摔碎。
一聽到這個問題,他頓時感覺無從下手,沒有絲毫的頭緒。但他嘗試著先從最簡單的情形入手:
- 若雞蛋數N=0或者樓層數為0,則嘗試0次即可。
- 若雞蛋數N=1, 對於樓層數為k,最壞的情況為嘗試k次,因此至少需要k次才能確定雞蛋從哪一層樓掉下去恰好摔碎。
有了最基本的情形還不夠,對於其他的N,k並沒有給出答案。這時,他想到自己這幾天正在研究的演算法:動態規劃法,他想也許這個演算法可以幫上忙。假設用numdrops(N,k)表示該問題的解。則將雞蛋從x層扔下,有以下兩種情形:
- 雞蛋摔碎了,此時剩下N-1個雞蛋,需要考慮比x層低的樓層,即1,2,...,x-1層,因為比x層高的樓層扔下去必定也摔碎,故可不比考慮。因此,這個問題會被縮減到numdrops(N-1, x-1).
- 雞蛋沒有摔碎,此時剩下N個雞蛋,需要考慮比x層高的樓層,即x+1, x+2,...,k層,共有k-x層。因此,問題會被縮減到numdrops(N, k-x).
對於以上兩種情形,應該去兩者的最大值。同時,考慮到x=1,2,3,...,k, 因此有如下公式:
有了以上演算法,再加上如下初始情況:
- numdrops(0, x)=0, numdrops(x,0)=0.
- numdrops(1, x)=x.
就可以用動態規劃法求解該問題了。他迅速地寫下了Python程式碼:
import numpy as np
def solvepuzzle(n, k):
numdrops = np.array([[0]*(k+1)]*(n+1))
for i in range(k+1):
numdrops[1, i] = i
for i in range(2, n+1):
for j in range(1, k+1):
minimum = float('inf')
for x in range(1, j+1):
minimum = min(minimum, (1+max(numdrops[i, j-x], numdrops[i-1, x-1])))
numdrops[i, j] = minimum
print(numdrops)
return numdrops[n,k]
t = solvepuzzle(3, 10)
print(t)
輸出結果如下:
[[ 0 0 0 0 0 0 0 0 0 0 0]
[ 0 1 2 3 4 5 6 7 8 9 10]
[ 0 1 2 2 3 3 3 4 4 4 4]
[ 0 1 2 2 3 3 3 3 4 4 4]]
4
這樣就可以求出該問題的解了,比如4個雞蛋10層樓,則只需要3次即可。
丁丁連忙把這個解答問題通過助手告訴了科學家。科學家聽後興奮不已,立馬叫丁丁過來討論。科學家對他說道:“你的解決方法是如此的巧妙,讓人歎為觀止,很難相信它是出自一個少年的腦袋中。但是,親愛的朋友,你能告訴我具體應該怎麼扔雞蛋呢?”
丁丁聽了,又是歡喜又有點擔心,因為科學家又提出了一個問題。他看看了輸出的numdrops表格,立馬就有了主意。
對於N=2,k=50的情形,numdrops(N,k)=10,給出的方案如下:
從哪一層扔雞蛋 | 雞蛋摔碎後的情形 | 次數 |
---|---|---|
10 | 1->2->3->4->5->6->7->8->9 | 9+1=10 |
19 | 11->12->13->14->15->16->17->18 | 8+2=10 |
27 | 20->21->22->23->24->25->26 | 7+3=10 |
34 | 28->29->30->31->32->33 | 6+4=10 |
40 | 35->36->37->38->39 | 5+5=10 |
45 | 41->42->43->44 | 4+6=10 |
49 | 46->47->48 | 3+7=10 |
50 | 8 |
嘗試著對上表做說明:先從第10層扔下,若雞蛋摔了,則還剩一個雞蛋,依次從1,2,3...9層扔下,若雞蛋沒碎,則失去了一次嘗試機會,再將雞蛋從19層扔下,若雞蛋碎了,則還剩一個雞蛋,依次從11,12,...,18層扔下......
對於N=4,k=20的情形,numdrops(N,k)=10,輸出的numdrops表如下:
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
[ 0 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6]
[ 0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 5 5 5 5 5 5]
[ 0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5 5]]
5
首先找到numdrops(3,14)=4, 次數比5小一次, 層樓k儘可能大,則將雞蛋從15扔下,若雞蛋沒碎,則剩下3個雞蛋,探索4層樓,因為numdrops(3,14)=4,故能完成。若雞蛋碎了,則再找到numdrops(2,6)=3,則將雞蛋從7樓扔下,若雞蛋碎了,則情形轉化為numdrops(2,6)的情形,若雞蛋沒碎,則用剩下的雞蛋探索7層樓,是可以搞定的。
當科學家看到這個結果後,滿意地點點頭,他想著是否要聘請這個少年來當自己的助手。不過,他決定再考驗丁丁一回~~
未完待續~~
注意:本人現已開通兩個微信公眾號: 用Python做數學(微訊號為:python_math)以及輕鬆學會Python爬蟲(微訊號為:easy_web_scrape), 歡迎大家關注哦~~
相關文章
- JAVA 雞蛋問題Java
- 動態規劃系列之六01揹包問題動態規劃
- 動態規劃法動態規劃
- 【動態規劃】揹包問題動態規劃
- 動態規劃之子序列問題動態規劃
- 揹包問題----動態規劃動態規劃
- 動態規劃_備忘錄法_矩陣鏈乘問題動態規劃矩陣
- 動態規劃--01揹包問題動態規劃
- 動態規劃篇——揹包問題動態規劃
- 動態規劃 01揹包問題動態規劃
- 動態規劃,股票問題留坑動態規劃
- 動態規劃之股票問題123動態規劃
- 動態規劃-01揹包問題動態規劃
- 找零問題與動態規劃動態規劃
- 【動態規劃】01揹包問題動態規劃
- 醜數問題——動態規劃、Java動態規劃Java
- 【動態規劃】01揹包問題【續】動態規劃
- 【必備演算法】動態規劃:一個思路解決六道股票問題演算法動態規劃
- 關於動態規劃法動態規劃
- 動態規劃題單動態規劃
- 好題——動態規劃動態規劃
- 動態規劃專題動態規劃
- 動態規劃使用一維陣列要注意的問題動態規劃陣列
- 【動態規劃】一次搞定三種揹包問題動態規劃
- 動態規劃,這幾個問題最常見!動態規劃
- 0-1揹包問題(動態規劃)動態規劃
- 矩陣連乘問題 Python 動態規劃矩陣Python動態規劃
- 從“股票問題”談動態規劃問題的解決思路動態規劃
- 動態規劃練習題動態規劃
- 動態規劃做題思路動態規劃
- 動態規劃解題方法動態規劃
- leetcode題解(動態規劃)LeetCode動態規劃
- 動態規劃解0-1揹包問題動態規劃
- 動態規劃問題為什麼要畫表格?動態規劃
- 最小總和問題(動態規劃演算法)動態規劃演算法
- 磁帶最大利用率問題——動態規劃動態規劃
- 迴文串問題(動態規劃DP C++)動態規劃C++
- 動態規劃之0,1揹包問題動態規劃