[leetcode] Super Egg Drop

题目

You are given K eggs, and you have access to a building with N floors from 1 to N.

Each egg is identical in function, and if an egg breaks, you cannot drop it again.

You know that there exists a floor F with 0 <= F <= N such that any egg dropped at a floor higher than F will break, and any egg dropped at or below floor F will not break.

Each move, you may take an egg (if you have an unbroken one) and drop it from any floor X (with 1 <= X <= N).

Your goal is to know with certainty what the value of F is.

What is the minimum number of moves that you need to know with certainty what F is, regardless of the initial value of F?


Example 1:

Input: K = 1, N = 2
Output: 2
Explanation:
Drop the egg from floor 1. If it breaks, we know with certainty that F = 0.
Otherwise, drop the egg from floor 2. If it breaks, we know with certainty that F = 1.
If it didn’t break, then we know with certainty F = 2.
Hence, we needed 2 moves in the worst case to know what F is with certainty.


Example 2:

Input: K = 2, N = 6
Output: 3


Example 3:

Input: K = 3, N = 14
Output: 4


Note:
1 <= K <= 100
1 <= N <= 10000

思路

把所需次数作为所求变量

这道题显然是一道动态规划的题目。假定我们现在有K个鸡蛋,N层楼,设需要 f ( K , N ) f(K, N) f(K,N)才能测出F的值。我们从第p层把鸡蛋扔下,有两种情况

  1. 鸡蛋破裂:说明F的值在 [ 1 , p − 1 ] [1,p-1] [1,p1]间,还需要投掷 f ( K − 1 , p − 1 ) f(K-1,p-1) f(K1,p1)
  2. 鸡蛋没有破裂:说明F的值在 [ p + 1 , N ] [p+1, N] [p+1,N]间,还需要投掷 f ( K , N − p ) f(K,N-p) f(K,Np)
    为了涉及两种情况,抛掷的次数应该不会小于上面两个值
    因此状态转移方程为
    f ( K , N ) = min ⁡ p m a x { f ( K − 1 , p − 1 ) , f ( K , N − p ) } f(K,N)=\min_p max\{f(K-1,p-1),f(K,N-p)\} f(K,N)=pminmax{f(K1,p1),f(K,Np)}
    状态数为 K N KN KN个,转移代价为 O ( K ) O(K) O(K),总复杂度为 O ( K 2 N ) O(K^2N) O(K2N)
    如果我们优化对p的寻找过程(二分查找,代码出处),转移代价可以减少为 O ( l o g K ) O(logK) O(logK),总复杂度为 O ( N K l o g K ) O(NKlogK) O(NKlogK)

把可测的层数作为所求变量

设给定鸡蛋个数K和可抛掷次数M,此时可测出的F的最大值记作 g ( M , K ) g(M, K) g(M,K)。注意到,当我们知道 g ( M − 1 , K − 1 ) g(M-1, K-1) g(M1,K1)时,我们可以从第 ( g ( M − 1 , K − 1 ) + 1 ) (g(M-1, K-1)+1) (g(M1,K1)+1)层抛出鸡蛋。结果如下:

  1. 鸡蛋破裂:说明F值在 [ 1 , g ( M − 1 , K − 1 ) ] [1,g(M-1, K-1)] [1,g(M1,K1)]间,这时候我们可以用 ( M − 1 ) (M-1) (M1)次抛掷得出F值
  2. 鸡蛋没有破裂:说明F值大于 ( g ( M − 1 , K − 1 ) + 1 ) (g(M-1, K-1)+1) (g(M1,K1)+1),此时剩下K个鸡蛋和 ( M − 1 ) (M-1) (M1)次机会最多可以测出的最大值不超过抛出层的 g ( M − 1 , K ) g(M-1, K) g(M1,K),因此,我们有状态转移方程:
    g ( M , K ) = g ( M − 1 , K ) + g ( M − 1 , K − 1 ) + 1 g(M,K)=g(M-1, K)+g(M-1,K-1)+1 g(M,K)=g(M1,K)+g(M1,K1)+1
    状态数为 K N KN KN个,转移代价为 O ( 1 ) O(1) O(1),总复杂度为 O ( K N ) O(KN) O(KN)

代码

class Solution {
public:
    int superEggDrop(int K, int N) {
        vector<vector<int>> dp(N + 1, vector<int>(K + 1, 0));
        int m = 0;
        while(dp[m][K] < N) {
            m++;
            for(int k = 1; k <= K; ++k)
                dp[m][k] = dp[m - 1][k - 1] + dp[m - 1][k] + 1;
        }
        return m;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值