100层楼扔2个鸡蛋、3个鸡蛋……

来源:互联网 发布:淘宝女装代销选货技巧 编辑:程序博客网 时间:2024/04/30 10:52

原题目

    现有2个鸡蛋,楼高100层,假设从n层楼及以上扔下会摔碎,n层以下不会,那么怎样扔能以最小的次数得到n?

分析

    最先想起来的是二分法的题目:100层最少需要扔多少次鸡蛋才能求得n?答案是ceil(log2(100))=7 。不过现在只有两个鸡蛋,这种方法就不行了。采用二分法的话,如果1号蛋在50层碎了,那剩下一个鸡蛋只能从1层开始慢慢扔了,需要扔1+49 = 50次。

    另外一种容易想起来的就是,1号蛋每两层扔一次,1、3、5、7……假设7层碎了,那2号蛋在6层再扔一次即可确定n。需要n/2+2次,最多需要扔51次。进而,如果1号蛋每m层扔一次,同样的策略最多需要扔100/m+m-1次。m取10,最坏情况下次数最小,为19次。

聪明的方法

    一种方法是限定扔的次数,看在最坏的情况下最多能在楼高多少层的情况下找出n。

    例如,限定最多扔15次,那么第一次在15层扔。碎的情况下可以使用2号蛋最多14次确定n,如果没有碎,则还剩下最多14次机会。这一次再隔14层(即15

14层)扔,同样的,如果碎掉,可以使用2号蛋最多13次确定n,如果没有碎,还剩下最多13次机会。那么继续,可以再隔13层扔……最后如果只剩一次,机会,则正好可以再确定一层楼。即总共可以确定 15 + 14 + 13 + …… + 1 = 120层楼。

    可以归纳出,限定最多扔e次,则最多可以处理的楼层数为:n + (n-1) + (n-2) + ……+ 1 = n*(n+1)/2。令可处理的楼层数大于100,得到n = 14。

动态规划解法及原题扩展

    从上面这种方法看到,采取隔m层扔的方法,最优的m值是随总的楼层数变化的,每一步间隔层数应该是变化的。如果用cnt[p][2]表示楼共有p层,2个鸡蛋情况下需要扔的次数,第一次从k层扔下,如果蛋碎了,总次数为cnt[k-1][1] + 1,如果没有碎,总次数为cnt[p-k][2] + 1,综合考虑这两种情况下的结果,需要取这两个值中的最大值。

    即有:cnt[p][2] = min{ max ( cnt[p-k][1] + 1, cnt[p-k][2] + 1) ,for k = 1,2,……p}

    其中,1个鸡蛋情况下p层楼需要扔的次数为p。

    这种动态规划的方法可以很轻易的扩展到多个鸡蛋,比如已知p层楼2个鸡蛋的答案,3个鸡蛋的答案由下式就可以得到:

    cnt[p][3] = min{ max ( cnt[p-k][2] + 1, cnt[p-k][3] + 1) ,for k = 1,2,……p}

    假设e个鸡蛋,p层楼,那么建一个p*e的数组,从第一列开始填就行了,复杂度为O(p^2 * e)。

5 3
原创粉丝点击