1. 程式人生 > >兩個軟硬程度一樣的雞蛋,它們在某一層摔下會碎,有個100層的建築,要求最多用兩個雞蛋確 定雞蛋安全下落的臨界位置,給出臨界位置?如果是n層樓,m個雞蛋,請給出確定臨界位置的演算法

兩個軟硬程度一樣的雞蛋,它們在某一層摔下會碎,有個100層的建築,要求最多用兩個雞蛋確 定雞蛋安全下落的臨界位置,給出臨界位置?如果是n層樓,m個雞蛋,請給出確定臨界位置的演算法

題目:問題:一幢大樓共計100層,某種型別的雞蛋從某一樓層及其以上樓層摔下來時會被打破,從該層樓(即臨界樓層)以下樓層摔下該雞蛋,雞蛋不會出現破損。現給你2個完全一樣的該種類型的雞蛋,問:如何通過這2個雞蛋找到該臨界樓層時,所用的摔雞蛋次數最少?

思考:給了我們2個雞蛋,意思就很明顯,有1個雞蛋起到關鍵作用,它可以被打破,以告訴我們臨界樓層大致在什麼位置。

初探:看到這個題,首先想到的是二分搜尋法,先從50樓摔下,分兩種情況:

1.如果沒碎:再從75樓(就是50+25=75)再次摔下。

2.如果碎了:第二個雞蛋從25樓摔下……

如此去找,但是我們可以發現裡面的漏洞,如果第二個雞蛋從25樓摔下也碎了怎麼辦?就找不到可以摔碎雞蛋的最低樓層了! 

二分搜尋失敗,但我們從中找到一點啟示:就是當我們找到一個雞蛋可以摔碎的樓層區間時,不能從中再擷取一段樓層再去扔,必須用順序輪詢法從低層到高層一層一層去找出那個樓層。(就像上面說的,如果雞蛋從50樓摔下,碎了,那麼第二個雞蛋必須從一樓開始扔:一樓、二樓、三樓。。。。。。直到找出可以摔碎雞蛋的樓層)。

所以思路出來了:開始可以分段去找出可以摔碎雞蛋的樓層段(我們稱之“高樓層分段找的次數”),然後再去輪詢這個分界點以下的樓層段的每一層樓,看是在哪一層樓可以把雞蛋摔碎(我們稱之“低樓層輪詢的次數”)。

解答:我們使用暴力破解法,什麼是暴力破解法?就是不存在僥倖心理(如果剛好碰到那個樓層就說我找到了摔碎雞蛋的樓層就是僥倖心理),我們所假設的都是最壞情況下的查詢次數。上圖嘍:


如果分得的第一段分界點在x=5處,那麼最壞情況下x左邊的查詢次數應該等於x右邊的查詢次數,即上圖中的“=”成立。

所以在x=5處分兩種情況:雞蛋碎了和沒碎。兩種情況的查詢次數應該相等。

1.     如果雞蛋沒碎:那麼說明所找樓層小於5,對於小於5的情況,必須輪詢,也就是“低樓層輪詢的次數”(參見上面思路),此時從1~4層輪詢需要4次,即低樓層輪詢次數=4。

2.     如果雞蛋碎了:那麼說明所找樓層大於5,對於大於5的情況,我們找樓層的次數=“高樓層分段找的次數”+“低樓層輪詢的次數”。此時第二個分界點就是9!為什麼呢?因為低樓層輪詢次數=4,高樓層分段+低樓層輪詢也一定要等於4,分段佔去一次(在9這個位置),那麼只能低樓層輪詢=3,輪詢6~8剛好等於3。

所以,如上圖,最壞情況下:如果雞蛋碎了,低樓層輪詢4次。如果沒碎,也是4次(9樓扔一次,假設沒碎,然後6、7、8樓各扔一次,加起來4次,與低樓層次數相同)。

所以:

第一個分界點為5,5的左邊要扔4次,5的右邊也等於4次;第一個樓層段為5(1~5樓);

第二個分界點為9,9的左邊要扔3次,9的右邊也等於3次;第二個樓層段為4(6~9樓);

……

假設第一個分界點為x,則第一段樓層段就是x,而第二個樓層段就是x-1,第三個樓段是x-2,……那總共有多少個樓層段呢?有x個!

把所有樓層加起來小於總樓層100,就是x+(x-1)+(x-2)+……+[x-(x-1)]= x+(x-1)+(x-2)+……+1<=100。解出x=14。

檢驗:把答案列出來更直觀:

第1次:14

第2次:+13=27

第3次:+12=39

第4次:+11=50

第5次:+10=60

第6次:+9=69

第7次:+8=77

第8次:+7=84

第9次:+6=90

第10次:+5=95

第11次:+4=99

第12次:+3=102

第13次:+2=104

第14次:+1=105

這是典型的動態規劃問題。假設f[n]表示從n層樓找到摔雞蛋不碎安全位置的最少判斷次數。假設第一個雞蛋第一次從第i層扔下,如果碎了,就剩一個雞蛋,為確定下面樓層中的安全位置,必須從第一層挨著試,還需要i-1次;如果不碎的話,上面還有n-i層,剩下兩個雞蛋,還需要f[n-i]次(子問題,實體n層樓的上n-i層需要的最少判斷次數和實體n-i層樓需要的最少判斷次數其實是一樣的)。因此,最壞情況下還需要判斷max(i-1,f[n-i])次。 狀態轉移方程:f[n] = min{ 1 + max(i - 1 ,f[n - i]) | i = 1 ..n }  初始條件: f[ 0 ] = 0 (或f[ 1 ] = 1  
現在推廣成n層樓,m個雞蛋: 
還是動態規劃。假設f[n,m]表示n層樓、m個雞蛋時找到摔雞蛋不碎的最少判斷次數。則一個雞蛋從第i層扔下,如果碎了,還剩m-1個雞蛋,為確定下面樓層中的安全位置,還需要f[i-1,m-1]次(子問題);不碎的話,上面還有n-i層,還需要f[n-i,m]次(子問題,實體n層樓的上n-i層需要的最少判斷次數和實體n-i層樓需要的最少判斷次數其實是一樣的)。 

狀態轉移方程:f[n,m] = min{ 1 + max(f[i - 1 ,m - 1 ], f[n - i,m]) | i= 1 ..n } 初始條件:f[i, 0 ] = 0 (或f[i, 1 ] = i),對所有i