100層樓2個雞蛋,如何得知雞蛋能承受幾層的撞擊


http://www.tuicool.com/articles/NzUNJr

http://blog.sina.com.cn/s/blog_6c813dbd0101bh98.html

有一棟樓共100層,一個雞蛋從第N層及以上的樓層落下來會摔破, 在第N層以下的樓層落下不會摔破。給你2個雞蛋,設計方案找出N,並且保證在最壞情況下, 最小化雞蛋下落的次數。 

我們先假設最壞情況下,雞蛋下落次數為x,即我們為了找出N,一共用雞蛋做了x次的實驗。 那么,我們第一次應該在哪層樓往下扔雞蛋呢?先讓我們假設第一次是在第y層樓扔的雞蛋, 如果第一個雞蛋在第一次扔就碎了,我們就只剩下一個雞蛋,要用它准確地找出N, 只能從第一層向上,一層一層的往上測試,直到它摔壞為止,答案就出來了。 由於第一個雞蛋在第y層就摔破了, 所以最壞的情況是第二個雞蛋要把第1到第y-1層的樓都測試一遍,最后得出結果, 噢,原來雞蛋在第y-1層才能摔破(或是在第y-1層仍沒摔破,答案就是第y層。) 這樣一來測試次數是1+(y-1)=x,即第一次測試要在第x層。OK, 那如果第一次測試雞蛋沒摔破呢,那N肯定要比x大,要繼續往上找,需要在哪一層扔呢? 我們可以模仿前面的操作,如果第一個雞蛋在第二次測試中摔破了, 那么第二個雞蛋的測試次數就只剩下x-2次了(第一個雞蛋已經用了2次)。 這樣一來,第二次扔雞蛋的樓層和第一次扔雞蛋的樓層之間就隔着x-2層。 我們再回過頭來看一看,第一次扔雞蛋的樓層在第x層,第1層到第x層間共x層; 第1次扔雞蛋的樓層到第2次扔雞蛋的樓層間共有x-1層(包含第2次扔雞蛋的那一層), 同理繼續往下,我們可以得出,第2次扔雞蛋的樓層到第3次扔雞蛋的樓層間共有x-2層, ……最后把這些互不包含的區間數加起來,應該大於等於總共的樓層數量100,即

x + (x-1) + (x-2) + ... + 1 >= 100 (x+1)*x/2 >= 100 

得出答案是14。

即我先用第1個雞蛋在以下序列表示的樓層數不斷地向上測試,直到它摔破。 再用第2個雞蛋從上一個沒摔破的序列數的下一層開始,向上測試, 即可保證在最壞情況下也只需要測試14次,就能用2個雞蛋找出從哪一層開始, 往下扔雞蛋,雞蛋就會摔破。

14, 27, 39, 50, 60, 69, 77, 84, 90, 95, 99, 100

比如,我第1個雞蛋是在第77層摔破的,那么我第2個雞蛋就從第70層開始,向上測試, 第二個雞蛋最多只需要測試7次(70,71,72,73,74,75,76),加上第1個雞蛋測試的 7次(14,27,39,50,60,69,77),最壞情況只需要測試14次即可得出答案。

這個問題還有一個泛化的版本,即d層樓,e個雞蛋,然后設計方案找出N, 使最壞情況下測試的次數最少。這個要用動態規划(DP)來解。 

f[d][e]表示d 層樓,e個雞蛋時,最壞情況下的測試次數,則:

f[d][e]=min{max(f[d-i][e]+1,f[i-1][e-1]+1)},i=1,2,...,d;

f[k][1]=k,0<=k<=d,f[0][0...e]=0;

實現代碼如下:

int min_testnumber(int d, int e)  
{  
        int **f=new int *[d+1];  
        int i,j,k;  
        for(i=0;i<=d;i++) f[i]=new int[e+1]; for(i=0;i<=d;i++) f[i][1]=i; for(i=0;i<=e;i++) f[0][e]=0; for(i=1;i<=e;i++) { for(j=1;j<=d;j++) { int tmp; int min_test=0x7FFFFFFF; for(k=1;k<=j;k++) { tmp=f[j-k][i]+1>f[k-1][i-1]+1?f[j-k][i]+1:f[k-1][i-1]+1; if(tmp>min_test) min_test=tmp; } f[j][i]=min_test; } } return f[d][e]; }

兩個軟硬程度一樣但未知的雞蛋,它們有可能都在一樓就摔碎,也可能從一百層樓摔下來沒事。

有座100層的建築,要你用這兩個雞蛋確定哪一層是雞蛋可以安全落下的最高位置。可以摔碎兩個雞蛋。

 最少需要幾次測試,才能得到摔碎雞蛋的樓層?方案如何?

================================================= 

對於這個問題,如果從編程角度而言,最簡單的思路是用動態規划的思想來解決,不過本文不將其從編程角度分析,而是從數學角度對問題進行論述。

 ================================================

對這個問題,原始問題——100層樓,最少需要幾次測試,才能得到摔碎雞蛋的樓層】,直接考慮不容易考慮,但是,如果將這個問題進行一種等價的轉換,這個問題將會變得非常容易解答。個人認為,這個轉換是解決這個問題的核心,這個轉換是:

          轉換問題——【兩個雞蛋,進行k次測試,最多可以測試幾層樓】

 

如果大家能想到將“原始問題”變為“轉換問題”,這個問題個人認為已經解決一半了,轉換后,這個問題豁然開朗,思路全開。

 

現在我們以“轉換問題”為模板進行考慮,有兩個雞蛋,第一個雞蛋如果破碎,第二個雞蛋就必須只能一層一層的測試了,而且,我們要求進行k次測試就將摔碎雞蛋的樓層必須找到.

=====================================================

考慮第一次測試。第一次測試的時候,第一個雞蛋不能放置的樓層太高了,否則,如果第一個雞蛋破碎,第二個雞蛋可能不能在k次測試后得到結果。但是也不能放置的矮了,因為如果放置的矮了,第一個雞蛋破碎了還好說,如果沒破,我們浪費了一次測試機會,也不能說是完全浪費了,不過至少是讓效用沒有最大化。所以,第一次測試的時候必須讓第一個雞蛋放置的不高不矮。

 

不高不矮是多高?高到如果第一個雞蛋破碎后第二個雞蛋剛好能完成k次測試得到結果這個目標。由此可知,第一次測試所在的樓層高度為k,如果第一次測試第一枚雞蛋破碎,則剩下k-1層樓,一層一層的試,k次一定能完成目標。

 

如果第一次測試,第一枚雞蛋沒有破碎,則我們現在只有k-1次測試機會了,而且直到了k樓及其以下都是安全的了。我們消耗了一次測試機會,但是一次就測試了k層樓。

 

然后只有k-1次機會了,第二次測試,我們可以在k層的基礎上再增加k-1層了,注意,這個時候由於我們只有k-1次機會,所以這次只能再增加k-1層,以保證測試的時候第一枚雞蛋破碎的情況下仍然能完成任務。

 

於是,重復上述過程,直到最后一次機會,我們總共測試的樓層數為:

      

然后,再回到“原始問題”,100層樓,如果需要k次測試才能測試完成,則必須有

 

則可以得到,k≥14

也就是需要14次測試才能得到結果,而且這個過程也將測試方案一並得出來,就是第一次在14樓測試,如果第一枚蛋碎,則剩余13次機會,13層未知樓層,恰好,第二次在14+13=27樓測試,如此。

如果不是100層,而是N層,需要的測試次數為k,則有

      

========================================================= 

然后,這個問題這個時候還可以擴展了,如果我們有三個雞蛋,有k次機會,我們最大可以測試多少層樓?

思路同前面一樣,第一次測試,不能太高也能太矮,必須恰到好處,也就是第一枚雞蛋如果破碎,剩余k-1次機會能將剩余樓層給測試完。

由上面結論,k-1次機會最多可以測試k(k-1)/2層樓,所以第一次在k(k-1)/2+1層樓,第一次如果第一枚雞蛋不碎,第二次在此基礎上增加(k-1)(k-2)/2+1層樓,於是,三個雞蛋k次機會總共測試樓層數為

 

k=9.

至於四個雞蛋,五個雞蛋,以至於M個雞蛋,可以以此類推,方法同上。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM