其他分享
首页 > 其他分享> > 鸡蛋掉落

鸡蛋掉落

作者:互联网

给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。

已知存在楼层 f ,满足 0 <= f <= n ,任何从 高于 f 的楼层落下的鸡蛋都会碎,从 f 楼层或比它低的楼层落下的鸡蛋都不会破。

每次操作,你可以取一枚没有碎的鸡蛋并把它从任一楼层 x 扔下(满足 1 <= x <= n)。如果鸡蛋碎了,你就不能再次使用它。如果某枚鸡蛋扔下后没有摔碎,则可以在之后的操作中 重复使用 这枚鸡蛋。

请你计算并返回要确定 f 确切的值 的 最小操作次数 是多少?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/super-egg-drop
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

import java.util.Scanner;

class Solution {

    public static int superEggDrop1(int K, int N) {

        int v = log2N(N) + 1;
        if (K >= v) {
            return v;
        }

        int[][] dp = new int[N + 1][K + 1];

        for (int i = 1; i <= N; ++i) {
            dp[i][1] = i;
        }

        for (int i = 1; i <= K; ++i) {
            dp[1][i] = 1;
        }

        for (int i = 2; i <= N; ++i) {

            for (int j = K; j >= 2; --j) {
                dp[i][j] = Integer.MAX_VALUE;

                for (int k = 1; k <= i; ++k) {
                    if (dp[i][j] > Math.max(dp[i - k][j], dp[k - 1][j - 1]) + 1) {
                        dp[i][j] = Math.max(dp[i - k][j], dp[k - 1][j - 1]) + 1;
                    }
                }
            }
        }
        return dp[N][K];
    }

    public static int superEggDrop2(int K, int N) {

        int v = (int) (Math.log(N) / Math.log(2)) + 1;
        if (K >= v) {
            return v;
        }

        int[][] dp = new int[N + 1][K + 1];
        int[][] choose = new int[N + 1][K + 1];

        for (int i = 1; i <= N; ++i) {
            dp[i][1] = i;
            choose[i][1] = 1;
        }

        for (int i = 1; i <= K; ++i) {
            dp[1][i] = 1;
            choose[1][i] = 1;
        }

        for (int i = 2; i <= N; ++i) {
            for (int j = K; j >= 2; --j) {
                dp[i][j] = Integer.MAX_VALUE;
                int down = Math.max(1, choose[i - 1][j]);
                int up = Math.min(j == K ? i : choose[i][j + 1], i);
                for (int k = down; k <= up; k++) {
                    /**
                     * 要更新右侧格子,所以等于
                     */
                    if (dp[i][j] >= Math.max(dp[k - 1][j - 1], dp[i - k][j]) + 1) {
                        dp[i][j] = Math.max(dp[k - 1][j - 1], dp[i - k][j]) + 1;
                        choose[i][j] = k;
                    }
                }
            }
        }
        return dp[N][K];
    }

    /**
     * dp[i][j]
     * dp[0][j] = 0
     * dp[i][0] = 0
     * i 个蛋,扔 j 次达到的最大高度
     *
     * @return
     */
    public static int superEggDrop(int K, int N) {

        int v = (int) (Math.log(N) / Math.log(2)) + 1;
        if (K >= v) {
            return v;
        }

        int[] dp = new int[K + 1];

        int ret = 0;

        while (true) {

            ret++;

            /**
             * dp[i][j] = dp[i][j - 1] + 1 + dp[i - 1][j - 1]
             *
             * 假设扔到最优位置
             *
             * 1. 没碎
             * dp[i][j - 1]
             *
             * 2. 碎了
             * dp[i - 1][j - 1]
             *
             */
            int previous = 0, tmp;
            for (int i = 1; i <= K; ++i) {
                tmp = dp[i];
                dp[i] = dp[i] + previous + 1;
                previous = tmp;
                if (dp[i] >= N) {
                    return ret;
                }
            }
        }
    }

    public static int log2N(int n) {
        int res = -1;
        while (n != 0) {
            res++;
            n >>>= 1;
        }
        return res;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            System.out.println(superEggDrop(in.nextInt(), in.nextInt()));
        }
    }
}

标签:return,int,鸡蛋,static,dp,new,掉落,Math
来源: https://www.cnblogs.com/tianyiya/p/15455470.html