1. Leecode高楼抛鸡蛋 --递归回溯法和动态规划法

这篇博客探讨了如何利用回溯法和动态规划解决一个经典的计算机科学问题:确定一栋楼中鸡蛋从哪一层扔下不会破碎。通过递归的回溯法实现和状态转移方程的动态规划方法,博主展示了如何在最坏情况下找到最小的扔鸡蛋次数。这两种算法都旨在优化搜索过程,减少试验次数。
摘要由CSDN通过智能技术生成

题⽬是这样:你⾯前有⼀栋从 1 到 N 共 N 层的楼,然后给你 K 个鸡蛋
( K ⾄少为 1)。现在确定这栋楼存在楼层 0 <= F <= N ,在这层楼将鸡
蛋扔下去,鸡蛋恰好没摔碎(⾼于 F 的楼层都会碎,低于 F 的楼层都不
会碎)。现在问你,最坏情况下,你⾄少要扔⼏次鸡蛋?

在这里插入图片描述

回溯法
public class ThrowAgg {

    public static void main(String[] args) {
        ThrowAgg ta = new ThrowAgg();
        // System.out.println(ta.innerLoop(1, 2));
        System.out.println(ta.innerLoop(2, 6));
        // System.out.println(ta.innerLoop(3, 14));
    }


    /**
     * 假设楼层只有6层,鸡蛋有2个,看最小次数是多少
     * 然后如果有13层,鸡蛋有2个,先从第7扔,没碎。那么问题就变成了,楼层只有6层,有2个鸡蛋,求最小次数。
     * 所以这就是动态规划先求子问题的由来。
     * dp[i][j]: 最高楼层为j,鸡蛋有i个,最小扔dp[i][j]次,能够找出鸡蛋恰好不会破的楼层F。
     */
     
    // 递归函数的意义:最高楼层为n,有k个鸡蛋,扔 innerLoop(k,n)次能够找出鸡蛋恰好不破的楼层f
    public int innerLoop(int k, int n) {

        if (k == 1) return n;
        if (n == 0) return 0;

        int res = Integer.MAX_VALUE;
        for (int i = 1; i <= n; i++) {
            res = Math.min(
                    res,
                    Math.max(
                            innerLoop(k - 1, i - 1),
                            innerLoop(k, n - i)
                    ) + 1);
        }
        return res;
    }

}
动态规划法
class ThrowAgg2 {

    public static void main(String[] args) {
        ThrowAgg2 ta = new ThrowAgg2();
        System.out.println(ta.dynamic(2, 6));
    }

    /**
     * 动态规划解决:遍历所有的状态,然后在选择中找到一个最好的。
     */
    // dp[2][4]:最高楼层为4,有2个鸡蛋,最少扔 dp[2][4]次能够找出鸡蛋恰好不破的楼层f
    public int dynamic(int k, int n) {
        int[][] dp = new int[k + 1][n + 1];
        for (int i = 1; i <= k; i++) {
            for (int j = 0; j <= n; j++) {
            // 因为比较最小值,所以把每个值先初始化成 最大值
                dp[i][j] = Integer.MAX_VALUE;
                if (i == 1) { //鸡蛋最少为1。base case:鸡蛋个数为1,那就全部都要试
                    dp[1][j] = j;
                    continue;
                }
                if (j == 0) { //base case:如果楼高为0,那一次都不用试
                    dp[i][0] = 0;
                    continue;
                }

                // 在碎和不碎里面找个层数最多的
                for (int m = 1; m <= j; m++) {
                    dp[i][j] = Math.min(
                            dp[i][j],
                            Math.max(
                                    dp[i - 1][m - 1], //
                                    dp[i][j - m]
                            ) + 1
                    );
                }
            }
        }
        return dp[k][n];
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值