Eggs Dropping puzzle(2 eggs, 100 floors)

题目如下:

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?)

  • 问题一: 只有一个鸡蛋的时候, 如何测试

    如果我们只有一个鸡蛋, 我们知道鸡蛋一旦碎了, 我们就没有鸡蛋了。 所以我们要找出这个使得鸡蛋恰好碎的critital floor楼层, 我们只能从第一层开始向上一层一层的找。

    所以最坏的情况下, 我们需要扔100次才能找到(即要么在100层, 要么在100层也不会碎)。

  • 问题二: 现在我们有两个鸡蛋, 我们该如何测试呢?

    我们可以从第50层开始扔, 这样我们就可以把我们的问题的规模减为一半了。 有两种可能:

    (1)蛋碎了, 我们知道critical floor在50层楼以下。 但是此时我们手里还剩下一只鸡蛋, 我们没有别的办法, 只能从第一层开始一层层的往上找。 最坏的情况下我们需要检查: 1(对应着第一个出师未捷的蛋) + 49 = 50次

    (2) 蛋没有碎。 此时我们比较lucky, 然后继续用这个蛋进行二分测试。

    无论如和, 我们去上述两种情况最坏的情况, 即50次了。

  • 问题三: 能否做的更好

    所以做的更好, 就是我们使得最坏情况下, 扔的次数是最小的。 我们可以选择按照如下的方式扔鸡蛋。

    选择10floor的strategy。 也就是选择第一只鸡蛋:先从10层开始扔, 如果碎了, 就用第二个鸡蛋check 1-9层。 如果没有碎, 继续用这一个鸡蛋从20层开始扔, 一直进行下去。

    最坏的情况下(即最大的扔鸡蛋的次数):

    到90次的时候第一个鸡蛋还没有碎。 但是在100次的时候碎了。然后我们用第二个鸡蛋测试从91层开始, 一层层的测试。 我们的次数是: 10(第一个蛋) + 9 = 19次。

    好的这个策略远好于第一个策略。

  • 问题四: 还能做到更好吗?

    我们可以选择minimization of maxmum regret的策略。

上述的办法是采用的等差数列的方式扔鸡蛋。 现在我们换个策略。 只要我们的第一个鸡蛋不碎, 我们就减少增加的楼层数进行扔鸡蛋。 这样就使得一旦我们的第一个鸡蛋碎了, 那么使用第二个鸡蛋测试所需要的次数的是递减的。 例如第一个鸡蛋在第一层就碎了与第一个鸡蛋在第二层碎了这两种可能对应的导致的第二个鸡蛋的测试次数是递减的。

如何找到第一个鸡蛋最开始的扔鸡蛋的层数。 我们按照如下方式计算出来:

(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) 重叠子问题

这个很容易看出来。

编程实现:

递归版本:

# include <cstdio>
# include <climits>

// A utility function to get maximum of two integers
int max(int a, int b) { return (a > b)? a: b; }

/* Function to get minimum number of trails needed in worst
  case with n eggs and k floors */
int eggDrop(int n, int k)
{
    // If there are no floors, then no trials needed. OR if there is
    // one floor, one trial needed.
    if (k == 1 || k == 0)
        return k;

    // We need k trials for one egg and k floors
    if (n == 1)
        return k;

    int min = INT_MAX, x, res;

    // Consider all droppings from 1st floor to kth floor and
    // return the minimum of these values plus 1.
    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;
}

/* Driver program to test to pront printDups*/
int main()
{
    int n = 2, k = 10;
    printf ("\nMinimum number of trials in worst case with %d eggs and "
             "%d floors is %d \n", n, k, eggDrop(n, k));
    return 0;
}

动态规划:

# include <cstdio>
# include <climits>

// A utility function to get maximum of two integers
int max(int a, int b) { return (a > b)? a: b; }

/* Function to get minimum number of trails needed in worst
  case with n eggs and k floors */
int eggDrop(int n, int k)
{
    /* A 2D table where entery eggFloor[i][j] will represent minimum
       number of trials needed for i eggs and j floors. */
    int eggFloor[n+1][k+1];
    int res;
    int i, j, x;

    // We need one trial for one floor and0 trials for 0 floors
    for (i = 1; i <= n; i++)
    {
        eggFloor[i][1] = 1;
        eggFloor[i][0] = 0;
    }

    // We always need j trials for one egg and j floors.
    for (j = 1; j <= k; j++)
        eggFloor[1][j] = j;

    // Fill rest of the entries in table using optimal substructure
    // property
    for (i = 2; i <= n; i++)
    {
        for (j = 2; j <= k; j++)
        {
            eggFloor[i][j] = INT_MAX;
            for (x = 1; x <= j; x++)
            {
                res = 1 + max(eggFloor[i-1][x-1], eggFloor[i][j-x]);
                if (res < eggFloor[i][j])
                    eggFloor[i][j] = res;
            }
        }
    }

    // eggFloor[n][k] holds the result
    return eggFloor[n][k];
}

/* Driver program to test to pront printDups*/
int main()
{
    int n = 2, k = 36;
    printf ("\nMinimum number of trials in worst case with %d eggs and "
             "%d floors is %d \n", n, k, eggDrop(n, k));
    return 0;
}

运行结果:

分析:

时间复杂度:O(nk^2)

空间复杂度:O(nk)

时间: 2024-11-03 01:36:41

Eggs Dropping puzzle(2 eggs, 100 floors)的相关文章

扔鸡蛋问题详解(Egg Dropping Puzzle)

http://blog.csdn.net/joylnwang/article/details/6769160 经典的动态规划问题,题设是这样的:如果你有2颗鸡蛋,和一栋36层高的楼,现在你想知道在哪一层楼之下,鸡蛋不会被摔碎,应该如何用最少的测试次数对于任何答案楼层都能够使问题得到解决. 如果你从某一层楼扔下鸡蛋,它没有碎,则这个鸡蛋你可以继续用 如果这个鸡蛋摔碎了,则你可以用来测试的鸡蛋减少一个 所有鸡蛋的质量相同(都会在同一楼层以上摔碎) 对于一个鸡蛋,如果其在楼层i扔下的时候摔碎了,对于任

扔鸡蛋问题具体解释(Egg Dropping Puzzle)

经典的动态规划问题,题设是这种: 假设你有2颗鸡蛋,和一栋36层高的楼,如今你想知道在哪一层楼之下,鸡蛋不会被摔碎,应该怎样用最少的測试次数对于不论什么答案楼层都可以使问题得到解决. 假设你从某一层楼扔下鸡蛋,它没有碎,则这个鸡蛋你能够继续用 假设这个鸡蛋摔碎了,则你能够用来測试的鸡蛋降低一个 全部鸡蛋的质量同样(都会在同一楼层以上摔碎) 对于一个鸡蛋,假设其在楼层i扔下的时候摔碎了,对于不论什么不小于i的楼层,这个鸡蛋都会被摔碎 假设在楼层i扔下的时候没有摔碎,则对于不论什么不大于i的楼层,这

lintcode584- Drop Eggs II- medium

There is a building of n floors. If an egg drops from the k th floor or above, it will break. If it's dropped from any floor below, it will not break. You're given m eggs, Find k while minimize the number of drops for the worst case. Return the numbe

[CareerCup] 6.5 Drop Eggs 扔鸡蛋问题

6.5 There is a building of 100 floors. If an egg drops from the Nth floor or above, it will break. If it's dropped from any floor below, it will not break. You're given two eggs. Find N, while minimizing the number of drops for the worst case 这道题说有10

Cracking the Coding Interview 6.5

There is a building of 100 floors. If an egg drops from the Nth floor or above, it will break. If it's dropped from any floor below, it will not break. You're given 2 eggs. Find N, while minimizing the number of drops for the worst case. 次数  阶数  如果破了

程序猿的自我修养清单

Data Structures 1. Integer – find number of 1s – next largest smaller – smallest larger number – determine if is palindrom – itoa, atoi – add 2 numbers w/o using + or arithmetic operators – implement *, -, / using only + – find max of two numbers w/o

python学习之函数

1.函数名可以被赋值 比如: def aaa(): pass b = aaa//将函数名字赋值给b b()//跟aaa()效果一样 2.return 2.1.如果函数不写return的话,会默认返回None 2.2.return后,函数下面的语句不会被执行,中断函数操作 2.3.return个什么东西都行,哪怕是个列表..... 3.pycharm使用断点调试的话,需要用debug模式(向右小箭头的小虫子) 4.参数: 默认参数必须写在后边 def aaa(a1, a2 = 1): pass//

python学习笔记系列----(一)python简介

一个月前,就按下决心要系统的学习下python了,虽然之前有学习过java,学习过c++,也能较为熟练的使用java做自动化测试看懂c++里的业务逻辑,但是实际上有那么多的东西自己还是不清楚,今天下定决心,开始了python的系统的学习之路,之前我是有看过廖学峰的教程的,看完收获确实也是少,但总感觉就是少了什么,后面想了下,我想应该是自己的学习方法~~~介于之前学习RF的经验,我认为看官方文档对于一个想系统学习python的人来说,真的是一个不能再好的学习方法,接下来我会开始坚持把python2

Codecademy python

#1 print "Welcome to Python!" #2 my_variable = 10 #3 # Set the variables to the values listed in the instructions! my_int = 7 my_float = 1.23 my_bool = True #4 # my_int is set to 7 below. What do you think # will happen if we reset it to 3 and p