Eggs Dropping puzzle(2 eggs, 100

2018-01-29  本文已影响38人  心彻

题目如下:

You are given two eggs, and access to a 100-storey building. Both eggs are identical. The aim is to find out the highest floor from which an egg will not break when dropped out of a window from that floor. If an egg is dropped and does not break, it is undamaged and can be dropped again. However, once an egg is broken, that is it for that egg.

If an egg breaks when dropped from floor n, then it would also have broken from any floor above that. If an egg survives a fall, then it will survive any fall shorter than that.

The question is: What strategy should you adopt to minimize the number egg drops it takes to find the solution?. (And what is the worst case for the number of drops it will take?)

上述的办法是采用的等差数列的方式扔鸡蛋。 现在我们换个策略。 只要我们的第一个鸡蛋不碎, 我们就减少增加的楼层数进行扔鸡蛋。 这样就使得一旦我们的第一个鸡蛋碎了, 那么使用第二个鸡蛋测试所需要的次数的是递减的。 例如第一个鸡蛋在第一层就碎了与第一个鸡蛋在第二层碎了这两种可能对应的导致的第二个鸡蛋的测试次数是递减的。
如何找到第一个鸡蛋最开始的扔鸡蛋的层数。 我们按照如下方式计算出来:
(1)第一个鸡蛋从楼层n开始向下扔, 如果碎了, 使用第二个鸡蛋一层层检查前面(n-1)层楼。
(2)如果第一个鸡蛋没有碎, 那么接下来, 我们从2n - 1层开始往下扔。 也就是说此时我们又向上走了n -1层开始扔第一个鸡蛋。 如果碎了, 用第二个鸡蛋检查前面n -1 层。 没有碎, 继续向下扔第一个鸡蛋。。
(3)第一个鸡蛋没有碎, 在楼层n + n - 1 + n -2 = 3n -3处扔鸡蛋。
依次进行下去。

我们有如下公式:
n + (n-1) + (n-2) + (n-3) + (n-4) + … + 1 >= 100
于是得到:
n (n+1) / 2 >= 100
计算得到:
n = 13.651。
我们取ceiling, 得到n = 14.
所以我们测试的情况如下:


测试情况

最坏的情况是我们扔了14次。 也就是我们第一次扔第一个蛋的时候, 这个悲催的家伙就碎了。 然后我们只能从一层开始向上, 逐层的用第二个蛋检查:
1 + 13 = 14。
下面我们使用动态规划求解这个题。
n个鸡蛋, k层楼。
一个问题要想搭上动态规划这趟高速列车, 那么这个问题的结构必须拥有如下两个优秀的特点。
(1)最优子结构
如果鸡蛋从x层向下扔的时候,会出现两个case:
– case 1: 鸡蛋碎了, 此时我们需要使用剩下的鸡蛋n - 1(假如我们有n 个鸡蛋)个鸡蛋去检查下面的x - 1层楼。

 k ==> Number of floors
 n ==> Number of Eggs
 eggDrop(n, k) ==> Minimum number of trails needed to find the critical floor in worst case.
  eggDrop(n, k) = 1 + min{max(eggDrop(n - 1, x - 1), eggDrop(n, k - x)): x in {1, 2, ..., k}}

(2) 重叠子问题
这个很容易看出来。
算法思路图:

算法思路图

递归版本的编程实现:

        static int max(int a, int b) => a > b ? a : b;

        /// <summary>
        /// Eggdrop the specified n and k.
        /// </summary>
        /// <returns>The eggdrop.</returns>
        /// <param name="n">鸡蛋数</param>
        /// <param name="k">楼层数</param>
        static int eggdrop(int n, int k)
        {
            if (n == 1)
            {
                return k;
            }
            if (k == 0||k==1)
            {
                return k;
            }
            int min = Int32.MaxValue;
            int x, res;
            for (x = 1; x <= k;x++)
            {
                res = max(eggdrop(n-1,x-1),eggdrop(n,k-x));
                if(res<min){
                    min = res;
                }
            }
            return min + 1;
        }

来源

需要注意的是,递归的效率特别慢,我们需要记住一句话,就是:

任何递归都可以用迭代去替换

这里要怎么用迭代去替换递归,我还在思考当中。。。

上一篇 下一篇

猜你喜欢

热点阅读