微軟的扔杯子問題 動態規劃

2021-06-14 01:54:27 字數 2900 閱讀 8418

題目描述

一種杯子,若在第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的值的最...

高樓扔雞蛋問題 動態規劃 反推演繹

對於高樓扔雞蛋問題,本文嘗試反其道而行之 首先描述乙個普適的高樓扔雞蛋問題,然後利用動態規劃法解決扔雞蛋次數的問題,最後由獲取次數的答案反推出扔雞蛋的方法。這種由次數答案反推出方法的演繹方式令人有點震驚,似乎不同於常見的人類思考方式,有點像 先假設再證明 一樣。感覺這個題目還有繼續深挖的可能,比如找...