1. 程式人生 > 其它 >leetcode-dp-hard-雞蛋掉落

leetcode-dp-hard-雞蛋掉落

package dp.superEggDrop;

/**
 * 887. 雞蛋掉落
 * 給你 k 枚相同的雞蛋,並可以使用一棟從第 1 層到第 n 層共有 n 層樓的建築。
 * <p>
 * 已知存在樓層 f ,滿足 0 <= f <= n ,任何從 高於 f 的樓層落下的雞蛋都會碎,從 f 樓層或比它低的樓層落下的雞蛋都不會破。
 * <p>
 * 每次操作,你可以取一枚沒有碎的雞蛋並把它從任一樓層 x 扔下(滿足 1 <= x <= n)。如果雞蛋碎了,你就不能再次使用它。如果某枚雞蛋扔下後沒有摔碎,則可以在之後的操作中 重複使用 這枚雞蛋。
 * <p>
 * 請你計算並返回要確定 f 確切的值 的 最小操作次數 是多少?
 * <p>
 * <p>
 * 示例 1:
 * <p>
 * 輸入:k = 1, n = 2
 * 輸出:2
 * 解釋:
 * 雞蛋從 1 樓掉落。如果它碎了,肯定能得出 f = 0 。
 * 否則,雞蛋從 2 樓掉落。如果它碎了,肯定能得出 f = 1 。
 * 如果它沒碎,那麼肯定能得出 f = 2 。
 * 因此,在最壞的情況下我們需要移動 2 次以確定 f 是多少。
 * 示例 2:
 * <p>
 * 輸入:k = 2, n = 6
 * 輸出:3
 * 示例 3:
 * <p>
 * 輸入:k = 3, n = 14
 * 輸出:4
 * <p>
 * <p>
 * 提示:
 * <p>
 * 1 <= k <= 100
 * 1 <= n <= 104
 */
public class superEggDrop {
    // 考慮每一層扔雞蛋,扔下去的結果兩種,碎、不碎
    // 如果碎了,說明F在0~i-1之間,還需要在1~i-1即i-1層樓中搜索
    // 如果沒有碎,說明F在i~N之間,還需要再i+1~N層即N-i層樓中搜索
    // 記dp[i][k]表示有k個雞蛋,i層樓中確定F的具體值的最小搜尋次數
    // 那麼,假設某次搜尋在第j樓,根據上面的思路,在第j樓扔下,存在兩種結果:碎、不碎
    // 然後根據結果分別在j樓上面或者下面的搜尋區間繼續搜尋F的值
    // 因此可以得到遞推公式
    // dp[i][k] =min{ max(dp[j-1][k-1], dp[i-j][k]) + 1 | 1<=j<=i  }
    // 顯然,k>=1,而i為0時,表示沒有任何樓層,那麼dp[0][k]=0
    // 當k=1,只有一個雞蛋,只能線性搜尋,dp[i][1]=i
    public static int superEggDrop(int k, int n) {

        int[][] dp = new int[k + 1][n + 1];
        for (int i = 0; i <= n; i++) {
            dp[1][i] = i;
        }

        for (int i = 2; i <= k; i++) {
            for (int j = 1; j <= n; j++) {
                Integer res = Integer.MAX_VALUE;
                for (int l = 1; l <= j; l++) {

                    res = Math.min(res, Math.max(dp[i - 1][l - 1], dp[i][j - l]) + 1);
                }
                dp[i][j] = res;
            }
        }
        return dp[k][n];
    }


    public static void main(String[] args) {
        System.out.println(superEggDrop(2, 6));
    }
}



不會,我可以學;落後,我可以追趕;跌倒,我可以站起來!