经典面试题楼层丢鸡蛋问题的动态规划解法与数学解法

原题:

2个鸡蛋,从100层楼上往下扔,以此来测试鸡蛋的硬度。比如鸡蛋在第9层没有摔碎,在第10层摔碎了,那么鸡蛋不会摔碎的临界点就是9层。

问:如何用最少的尝试次数,测试出鸡蛋不会摔碎的临界点?

注意:只有两个鸡蛋。第一个鸡蛋碎了,第二个鸡蛋只能挨个楼层测试了。

动态规划解法:

    //height为楼层数
    const int maxHeight = 100;
    int dp[maxHeight + 5] = { 0 };
    for (int height = 1; height <= maxHeight; height++)
    {
        dp[height] = height;//最土的方法,只用第一个鸡蛋从1层开始往上试
        for (int mid_h = 2; mid_h <= height; mid_h++) //第一个鸡蛋从mid_h开始丢
        {
            // mid_h-1 第一个鸡蛋碎了,第二个鸡蛋只能挨个试mid_h-1次;
            // dp[height-mid_h] 第一个鸡蛋没碎,两个鸡蛋剩下只需测dp[height-mid_h]次
            dp[height] = min(dp[height], 1 + max(mid_h - 1, dp[height - mid_h]));
            //取max之后的min,则是最坏情况下的最优解法
        }
    }
    // 动态规划完毕,看看结果
    for (int height = 1; height <= maxHeight; height++)
    {
        printf("%4d %4d \n", height, dp[height]);
    }

数学解法:别人的

 

 

题目延伸:有M层楼 / N个鸡蛋,要找到鸡蛋摔不碎的临界点,需要尝试几次?

图非原创,结果如图所示。

动态规划解法:

    //楼层 鸡蛋数
    int dp[105][105] = { 0 };
    int maxHeight = 100, maxEggs = 100;
    for (int height = 1; height <= maxHeight; height++)
        dp[height][1] = height;
    for (int eggs = 1; eggs <= maxEggs; eggs++)
        dp[1][eggs] = 1;
    for (int height = 2; height <= maxHeight; height++){
        for (int eggs = 2; eggs <= maxEggs; eggs++){
            int mid_h = 1;//第一个鸡蛋丢第一层
            //dp[mid_h-1][eggs-1]碎了 , dp[height-mid_h][eggs]没碎。取max即最坏情况,再加上这一次的测试
            dp[height][eggs] = 1 + max(dp[mid_h - 1][eggs - 1], dp[height - mid_h][eggs]);
            for (mid_h = 2; mid_h <= height; mid_h++) //第一个鸡蛋丢第mid_h层
            {    //最坏情况的最小测试次数
                dp[height][eggs] = min(dp[height][eggs], 1 + max(dp[mid_h - 1][eggs - 1], dp[height - mid_h][eggs]));
            }
        }
    }
    //动态规划完毕,看看结果
    for (int height = 1; height <= 100; height++){
        for (int eggs = 1; eggs <= 2; eggs++) {
            printf("%4d ", dp[height][eggs]);
        }
        printf("\n");
    }

 

posted @ 2018-07-07 16:22  fdu_taoshiqian  阅读(2849)  评论(0编辑  收藏  举报