实际上,我们的终极目的是要找出连续的两层楼i,i+1在楼层i鸡蛋没有摔碎,在楼层i+1鸡蛋碎了,问题的关键之处在于,测试之前,你并不知道鸡蛋会在哪一层摔碎,你需要找到的是一种测试方案,这种测试方案,无论鸡蛋会在哪层被摔碎,都至多只需要m次测试,在所有这些测试方案中,m的值最小。 对于只有1颗鸡蛋的情况,我们别无选择,只能从1楼开始,逐层向上测试,直到第i层鸡蛋摔碎为止,这时我们知道,会让鸡蛋摔碎的楼层就是i(或者直到顶层,鸡蛋也没有被摔碎),其他的测试方案均不可行,因为如果第1次测试是在任何i>1的楼层扔下鸡蛋,如果鸡蛋碎了,你就无法确定,i-1层是否也会令鸡蛋摔碎。所以对于1颗鸡蛋而言,最坏的情况是使鸡蛋摔碎的楼层数i>=36,此时,我们需要测试每个楼层,总共36次,才能找到最终结果,所以1颗鸡蛋一定能解决36层楼问题的最少测试次数是36. 对于2个鸡蛋,36层楼的情况,你可能会考虑先在第18层扔一颗,如果这颗碎了,则你从第1层,到第17层,依次用第2颗鸡蛋测试,直到找出答案。如果第1颗鸡蛋没碎,则你依然可以用第1颗鸡蛋在27层进行测试,如果碎了,在第19~26层,用第2颗鸡蛋依次测试,如果没碎,则用第1颗鸡蛋在32层进行测试,……,如此进行(有点类似于二分查找)。这个解决方案的最坏情况出现在结果是第17/18层时,此时,你需要测试18次才能找到最终答案,所以该方案,解决36层楼问题的测试次数是18. 相较于1颗鸡蛋解决36层楼问题,测试次数实现了减半,但是18并不是确保解决2颗鸡蛋,36层楼问题的最小值(实际的最小值是8).
我们可以将这样的问题简记为W(n,k),其中n代表可用于测试的鸡蛋数,k代表被测试的楼层数。对于问题W(2,36)我们可以如此考虑,将第1颗鸡蛋,在第i层扔下(i可以为1~k的任意值),如果碎了,则我们需要用第2颗鸡蛋,解决从第1层到第i-1层楼的子问题W(1,i-1),如果这颗鸡蛋没碎,则我们需要用这两颗鸡蛋,解决从i+1层到第36层的子问题W(2,36-i),解决这两个问题,可以分别得到一个尝试次数p,q,我们取这两个次数中的较大者(假设是p),与第1次在i层执行测试的这1次相加,则p+1就是第一次将鸡蛋仍在i层来解决W(2,36)所需的最少测试次数次数ti。对于36层楼的问题,第一次,我们可以把鸡蛋仍在36层中的任何一层,所以可以得到36中解决方案的测试次数T{t1,t2,t3,……,t36},在这些结果中,我们选取最小的ti,使得对于集合T中任意的值tj(1<=j<=36,j!=i),都有ti<=tj,则ti就是这个问题的答案。用公式来描述就是W(n, k) = 1 + min{max(W(n -1, x -1), W(n, k - x))}, x in {2, 3, ……,k},其中x是第一次的测试的楼层位置。 其中W(1,k) = k(相当于1颗鸡蛋测试k层楼问题),W(0,k) = 0,W(n, 0) = 0 所以在计算W(2,36)之前,我们需先计算出所有W(1,0),……,W(1,36),W(2,0),……,W(2,35)这些的值,可以用递推的方法实现,
|