題目描述
一種杯子,若在第n層被摔破,則在任何比n高的樓層均會破,若在第m層不破,則在任何比m低的樓層均不會破,給你兩個這樣的杯子,讓你在100層高的樓層中測試,要求用最少的測試次數找出恰巧會使杯子破碎的樓層。
不等式解法
所有討論基於2個杯子的情況:
下圖中所有圖示的紅線均表示剩下兩個杯子的時候的試摔位置,當杯子破碎後,也就是只剩下乙個杯子的時候,只需要從已知範圍的最底層向已知範圍的最高層逐層試摔。
當只有一層的時候,需要一次試摔。當有兩層的時候,需要兩次試摔。
當需要三層時候,首先討論是否可以通過兩次試摔完成,可以發現可以,方法如圖。
當需要四層時候,首先討論是否可以通過兩次試摔完成,可以發現已經不行,因此至少需要三次試摔。
當需要五層時候,首先討論是否可以通過小於等於三次試摔完成,如果不行則討論最多四次試摔的情況。依次類推,如下圖:
因此,當有100層的時候,最多需要n次試摔,使得 n+(n-1)+(n-2)+...+1 >= 100,然後對n上取整,因此n=14。最差情況需要14次試摔。試摔方法為:第一次在14層扔,如果沒破,在27層(14+13)繼續扔,不破在39層(27+12)繼續扔,依次類推。 如果破了,剩下乙個杯子,從已知範圍的最底層向已知範圍的最高層逐層試摔。
動態規劃解法
假設用dp[i][j]表示剩餘i層,j個杯子時候最少需要多少次試摔。
(1)dp[i][1] = i,也就是說當只剩下乙個杯子時,只能從第一層開始逐層向上試摔。
(2)dp[0][j] = 0,當只剩下0層時,只需要進行0次試摔。
(3)dp[1][j] = 1,當只剩下1層時,只需要進行1次試摔,前提是j>0
(4)dp[i][j] = min(1=
route[i][j],表示剩下i層j個杯子時,下一次試摔的樓層。當j=1時,從這個範圍內的最底層依次向最高層試摔。
[cpp]view plain
copy
#include
#define layer 101
#define cup 3
intmain()
for(i=1; i
dp[1][i] = 1;
route[1][i] = 0;
dp[0][i] = 0;
}
for(i=2; i
for(j=2; j
dp[j][i] = j;
route[j][i] = 0;
for(k=1; k
intmin = dp[k-1][i-1] > dp[j-k][i]? dp[k-1][i-1]+1: dp[j-k][i]+1;
route[j][i] = min <= dp[j][i]? k: route[j][i];
dp[j][i] = min
} }
printf("min step is %d\n"
, dp[layer-1][cup-1]);
//for(i=1; i
return
0;
}
輸出結果為:min step is 14。也就是,有一種方法,最多需要試摔14次。同時route陣列列印出了方法。
比如route陣列的結果:
route[i][2]10
2132
4353
6374
8494
104115
125135
145155
166176
186196
206216
227237
247257
267277
287298
308318
328338
348358
368379
389399
409419
429439
449459
4610
4710
4810
4910
5010
5110
5210
5310
5410
5510
5611
5711
5811
5911
6011
6111
6211
6311
6411
6511
6611
6712
6812
6912
7012
7112
7212
7312
7412
7512
7612
7712
7812
7913
8013
8113
8213
8313
8413
8513
8613
8713
8813
8913
9013
9113
9214
9314
9414
9514
9614
9714
9814
9914
10014
因此,route[100][2]=14,第一次試摔是在14層,如果碎了,那麼從第一層開始往14層試摔,如果沒碎,第二次試摔是在route[100-14][2]=route[86][2]=13,也就是在14+13=27層進行第二次試摔,如果這次碎了,那麼從第14+1=15層開始向上試摔,如果這次沒碎,第三次試摔是在route[86-13][2]=route[73][2]=12,也就是在27+12=39層開始試摔,依次類推。
微軟的扔杯子問題 動態規劃
題目描述 一種杯子,若在第n層被摔破,則在任何比n高的樓層均會破,若在第m層不破,則在任何比m低的樓層均不會破,給你兩個這樣的杯子,讓你在100層高的樓層中測試,要求用最少的測試次數找出恰巧會使杯子破碎的樓層。不等式解法 所有討論基於2個杯子的情況 下圖中所有圖示的紅線均表示剩下兩個杯子的時候的試摔...
扔雞蛋 (動態規劃)
你將獲得k個雞蛋,並可以使用一棟從1到n共有n層樓的建築。每個蛋的功能都是一樣的,如果乙個蛋碎了,你就不能再把它掉下去。你知道存在樓層f,滿足0 f n任何從高於f的樓層落下的雞蛋都會碎,從f樓層或比它低的樓層落下的雞蛋都不會破。你的目標是確切地知道f的值是多少。無論f的初始值如何,你確定f的值的最...
高樓扔雞蛋問題 動態規劃 反推演繹
對於高樓扔雞蛋問題,本文嘗試反其道而行之 首先描述乙個普適的高樓扔雞蛋問題,然後利用動態規劃法解決扔雞蛋次數的問題,最後由獲取次數的答案反推出扔雞蛋的方法。這種由次數答案反推出方法的演繹方式令人有點震驚,似乎不同於常見的人類思考方式,有點像 先假設再證明 一樣。感覺這個題目還有繼續深挖的可能,比如找...