題目連結:
給定兩正整數 k 、 n (1 ≦ k ≦ 100 , n < 2 ^ 63;當 k = n = 0 時,代表輸入結束),代表有 k 顆一模一樣的水球,以及一棟有 n 層樓的建築。
試問:最少需要丟幾次水球,才能保證知道水球從哪層樓丟下會剛好摔破?如果次數超過 63 次,請輸出「More than 63 trials needed.」;否則,直接輸出所需的次數。
注:水球破了就破了,無法復原。因此 k 顆都破了就無法得知結果(除非第 k 顆剛好可以測出)。而沒有破的水球,可以重複利用。
2 100
10 786599
4 786599
60 1844674407370955161
63 9223372036854775807
0 0
14
21
More than 63 trials needed.
61
63
原本的題目敘述相當抽象(對本人來說,不管是 ZeroJudge 還是 UVa 原題都是),所以稍作調整變成上面的題目大意。
我們定義一個二維陣列 Di, j ,i 代表擁有的水球數、 j 代表投水球的「次數」,而 Di, j 代表的是在一開始有 i 顆水球的情況下,且丟了 j 次水球(不一定是同一顆)後可以確定到多高的樓層數。
因此,來討論水球破與不破的情形:
水球破了 → 那麼就是從丟的樓層往下找,因為要確定到盡可能高的樓層,所以本次丟的樓層應為第 Di-1, j-1 + 1 層。(因為水球破了一顆且能丟的次數少了一次)。
水球沒破 → 那就是看從丟的樓層往上找,最高可以再找多少層,此時即 Di, j-1 (因為水球沒破,所以數量不變但次數仍少了一次)。
所以,最後我們可以得出:
Di, j = Di-1, j-1 + 1 + Di, j-1
且初始條件(邊界條件)是沒有水球或是沒有可丟的次數之情況:
對於任意非負整數 i , Di, 0 = D0, i = 0
然後從邊界條件往上推得測試資料可能會出現的情況。接著,每輸入一組(k, n)時,就從 Di, 1 、 Di, 2 、…… 開始找,找到第一個 Di, j 所確定的樓層大於等於 n 。此時即為所求。如果 j > 63 ,則輸出「More than 63 trials needed.」。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。