zoukankan      html  css  js  c++  java
  • 经典面试题楼层丢鸡蛋问题的动态规划解法与数学解法

    原题:

    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 
    ", 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("
    ");
        }
  • 相关阅读:
    WebApi 接口参数不再困惑:传参详解
    dataType和contentType的区别
    WaitHandles 的数目必须少于或等于 64 个--任意线程信号量监视
    跨线程调用DataGridView控件
    (转)调整.NET控件WebBrowser的默认浏览器内核版本
    Winform中checklistbox控件的常用方法
    csuoj 残缺的棋盘
    csuoj 你经历过绝望吗?两次! bfs + 优先队列
    csuoj barricade
    csuoj 集训队分组
  • 原文地址:https://www.cnblogs.com/taoshiqian/p/9277626.html
Copyright © 2011-2022 走看看