动态规划典中典之高楼扔鸡蛋

222 阅读1分钟

你面前有一栋从 1 到 N 共 N 层的楼,然后给你 K 个鸡蛋(K 至少为 1)。现在确定这栋楼存在楼层 0 <= F <= N,在这层楼将鸡蛋扔下去,鸡蛋恰好没摔碎(高于 F 的楼层都会碎,低于 F 的楼层都不会碎)。现在问你,最坏情况下,你至少要扔几次鸡蛋,才能确定这个楼层 F 呢?

class Solution {
public:
    int superEggDrop(int k, int n) {
        // 边缘场景
        if(k == 1) {
            return n;
        }
        if(n == 1) {
            return 1;
        }
        // dp定义:min_cnt[i][j] 表示用 i 个鸡蛋测试 j 层楼哪层开始鸡蛋会碎的最少尝试次数
        vector<vector<int>> min_cnt(k+1, vector<int>(n+1, n));
        // 楼层为1只需要尝试1次
        for(int eggs = 1; eggs <= k; eggs++) {
            min_cnt[eggs][1] = 1;
        }
        // 鸡蛋只有1个只能从1楼测试到顶楼
        for(int height = 1; height <= n; height++) {
            min_cnt[1][height] = height;
        }

        for(int eggs = 2; eggs <= k; eggs++) {
            for(int height = 2; height <= n; height++) {
                // 尝试次数最多是1个鸡蛋从1楼测试到顶楼,即楼层高度
                min_cnt[eggs][height] = height;
                // 枚举此次选择的楼层
                for(int floor = 1; floor <= height; floor++) {
                    // 鸡蛋没碎往上走
                    int min_cnt_ok = min_cnt[eggs][height-floor]+1;
                    // 鸡蛋碎了往下走,鸡蛋也少了一个
                    int min_cnt_broken = min_cnt[eggs-1][floor-1]+1;
                    min_cnt[eggs][height] = min(min_cnt[eggs][height], max(min_cnt_ok, min_cnt_broken));
                }
            }
        }
        return min_cnt[k][n];
    }
};