题目
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层把鸡蛋扔下,有两种情况
- 鸡蛋破裂:说明F的值在 [ 1 , p − 1 ] [1,p-1] [1,p−1]间,还需要投掷 f ( K − 1 , p − 1 ) f(K-1,p-1) f(K−1,p−1)次
- 鸡蛋没有破裂:说明F的值在
[
p
+
1
,
N
]
[p+1, N]
[p+1,N]间,还需要投掷
f
(
K
,
N
−
p
)
f(K,N-p)
f(K,N−p)次
为了涉及两种情况,抛掷的次数应该不会小于上面两个值
因此状态转移方程为
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(K−1,p−1),f(K,N−p)}
状态数为 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(M−1,K−1)时,我们可以从第 ( g ( M − 1 , K − 1 ) + 1 ) (g(M-1, K-1)+1) (g(M−1,K−1)+1)层抛出鸡蛋。结果如下:
- 鸡蛋破裂:说明F值在 [ 1 , g ( M − 1 , K − 1 ) ] [1,g(M-1, K-1)] [1,g(M−1,K−1)]间,这时候我们可以用 ( M − 1 ) (M-1) (M−1)次抛掷得出F值
- 鸡蛋没有破裂:说明F值大于
(
g
(
M
−
1
,
K
−
1
)
+
1
)
(g(M-1, K-1)+1)
(g(M−1,K−1)+1),此时剩下K个鸡蛋和
(
M
−
1
)
(M-1)
(M−1)次机会最多可以测出的最大值不超过抛出层的
g
(
M
−
1
,
K
)
g(M-1, K)
g(M−1,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(M−1,K)+g(M−1,K−1)+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;
}
};