再談大樓扔雞蛋的問題

2021-09-01 17:35:24 字數 4329 閱讀 6121

這道題是說,100層樓,兩個一模一樣的雞蛋,某層之上扔雞蛋就會碎。問要測試多少次才能找出這層樓來。我曾經在去年初的這篇文章裡面討論過這個問題的解法,因為只想記錄一下思路和討論過程,寫得很簡略。現在,我想重新整理一下這個問題,再稍稍擴充套件和挖掘一下。希望可以用盡可能清晰易懂的描述,把這個問題的前後說清楚。

現在只有兩個雞蛋,而演算法必須是可行的,就是說要能找出這一層來,所以你得假設你的運氣最差,這就意味著,我求解的是在每種扔雞蛋的策略下都有乙個需要扔的次數的最大值,而現在需要求解的是這些最大值中的最小值的問題。如果我只有一枚雞蛋,這就意味著,我只能從第一層開始老老實實地一層一層往上試,不能越層;而我的運氣非常非常差,於是我這樣試驗的結果就是一直試驗到最高一層雞蛋依然沒破,試驗的次數就等於樓層數n。

動態規劃法求解

現在,我有兩枚雞蛋,第一枚雞蛋從哪一層樓開始扔就顯得至關重要了。如果第一枚雞蛋碎了,那就回到剛說的只有一枚雞蛋的問題了。我相信很多人立即對映到腦子裡的詞是「二分法」,也就是說,第一枚雞蛋從n/2開始扔,如果碎了,扔的樓層數就是n/2(注意取整);如果沒碎,剩下n/2樓層裡繼續用二分法。可以預計,如果沒碎的情況,扔雞蛋的總次數要小於n/2。也就意味著,還有潛力可挖,如果不用二分法,讓扔第一枚雞蛋的樓層數為x,它小於n/2;同時如果第一枚雞蛋沒碎,接下去的策略,在運氣最差的情況下仍然讓扔的次數等於x,就最經濟了。

最常規的解法是動態規劃。可以用動態規劃法求解的問題必須滿足這樣的條件,分割成的子問題是最優解的時候,原問題也是最優解。顯然這個問題滿足這一點:假設扔的總次數為f(x),在第一次扔碎了的情況下,接下去只能一層一層試驗,最多從第1層到第x-1層需要試驗x-1次,加上扔第乙個雞蛋那一次,總的次數就是(x-1)+1=x;在第一次沒碎的情況下,就相當於乙個新的相似子問題:在n-x層中尋找新的扔雞蛋次數f(n-x),因此總次數就是f(n-x)+1。那麼:

f(x)=max(x, f(n-x)+1)

同時,遞迴求解的出口是:當x=1,f(x)=1。所以,演算法大致如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

// times[i]表示n取值為i的時候,需要扔多少次

privatestaticinttimes;

publicstaticintdropegg(intn)

privatestaticintdp(intn)

returntimes[n];

}

// 碎和不碎的次數最大值

privatestaticintmaxtimes(intn,intx)

「兩個雞蛋」到「m個雞蛋」

現在把問題擴充套件一下,由兩個雞蛋擴充套件到m個雞蛋,times陣列第一維表示最多可以扔幾次,第二維表示扔第幾次:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

publicstaticintdropegg(intn,intm)

privatestaticintdp(intn,intm)

returntimes[m][n];

}

// 碎和不碎的次數最大值

privatestaticintmaxtimes(intn,intx,intm)

尋找規律

還是回到兩個雞蛋,隨著n的值改變,可以發現x呈現這樣的變化:

n=1, x=1

n=2, x=2

n=3, x=2

n=4, x=3

n=5, x=3

n=6, x=3

n=7, x=4

n=8, x=4

n=9, x=4

n=10, x=4

n=11, x=5

n=12, x=5

n=13, x=5

n=14, x=5

n=15, x=5

n=16, x=6

n=17, x=6

n=18, x=6

n=19, x=6

n=20, x=6

n=21, x=6

……換言之,x=1的有1項,x=2的有2項,x=3的有3項……網上最多的問法是當n=100的時候,x是多少,根據這個規律:

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

得知x的最小值是14。

下面來證明一下這個猜想:

因為當扔雞蛋的最小次數為x的時候,第一次從x層開始扔,如果碎了,那麼接下去就要扔x-1次;如果沒碎,接下去就變成了扔雞蛋最小次數為x-1的子問題了,此時再扔的樓層數變成了x+(x-1),在這種情況下碎和不碎兩種情況下需要再扔的次數是相等的,已經是最經濟的扔法了,繼續之,可以得到,扔雞蛋最小次數為x的時候,最高可以檢測到的樓層數為:

x+(x-1)+(x-2)+……+1

正好是乙個等差數列求和的公式。

這也是為什麼,我們可以從網上找到的扔雞蛋問題,好多都是n等於15、21、28、36這樣的數,這正好等於這個等差數列和。

現在把問題稍稍轉變一下,把雞蛋數量的限制去掉,再把求爬樓梯的限制加上,不妨再來求解:

如果雞蛋數量無限,但是假如說扔一次雞蛋需要耗費力氣a,每爬一層樓(無論向上還是向下)需要耗費力氣b,現在用怎樣的扔雞蛋策略,可以讓耗費的總力氣量最小?

大樓扔雞蛋問題 dp poj 3783

題意分析 經典題,小白書上的一道例題,4 2出了這道原題,我愣是以為是數學題,最後也沒做出來。題意是這樣的,給你n個雞蛋 硬度一樣 讓你測雞蛋的硬度,測量的方法就是從某棟m層的樓的某一層x上把雞蛋扔下來,如果雞蛋碎了,代表他的強度小於x 如果沒碎,則強度大於等於x。我們要做的就是不斷的從樓上把雞蛋扔...

扔雞蛋問題

因為就乙個雞蛋,所以,我們很容易就可以想到從第一層開始扔就可以了,直到碎,說明這是n 1層。這裡當然也可以按照第乙個問題的方法來實現,即從第一層開始向上,直到摔碎為止,但是這種方法顯然是低效的。方法二 二分查詢 當時就想到了使用這種方法,即採用二分查詢的思路,第一次在50層扔 如果碎了,那麼從第一層...

扔雞蛋問題

因為就乙個雞蛋,所以,我們很容易就可以想到從第一層開始扔就可以了,直到碎,說明這是n 1層。這裡當然也可以按照第乙個問題的方法來實現,即從第一層開始向上,直到摔碎為止,但是這種方法顯然是低效的。方法二 二分查詢 當時就想到了使用這種方法,即採用二分查詢的思路,第一次在50層扔 如果碎了,那麼從第一層...