题目
你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑。
每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。
你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。
每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层 X 扔下(满足 1 <= X <= N)。
你的目标是确切地知道 F 的值是多少。
无论 F 的初始值如何,你确定 F 的值的最小移动次数是多少?
示例 1:
输入:K = 1, N = 2
输出:2
解释:
鸡蛋从 1 楼掉落。如果它碎了,我们肯定知道 F = 0 。
否则,鸡蛋从 2 楼掉落。如果它碎了,我们肯定知道 F = 1 。
如果它没碎,那么我们肯定知道 F = 2 。
因此,在最坏的情况下我们需要移动 2 次以确定 F 是多少。
示例 2:
输入:K = 2, N = 6
输出:3
示例 3:
输入:K = 3, N = 14
输出:4
提示:
1 <= K <= 100
1 <= N <= 10000
假设总共有K个鸡蛋,共有N层楼。
现在站在X层扔鸡蛋,如果鸡蛋没碎,那就带着K个鸡蛋在[X+1, N]楼层中扔鸡蛋(转化为K个鸡蛋,N-X层建筑的问题);
如果鸡蛋碎了,那就带着K-1个鸡蛋在[1, X-1]楼层中扔鸡蛋。
题目中“无论F的初始值如何”,所以上述两种情况中选择较大的移动次数作为X层开始扔鸡蛋确定F值的结果。
题目中“确定F值的最小移动次数”,遍历N层,每层作为扔鸡蛋起始层的结果中取最小值,也就是说存在某一层,在这层开始扔鸡蛋比在其它层开始扔鸡蛋的代价小,找出这个最小值。
这是一个动态规划问题。
class Solution {
public:
int superEggDrop(int K, int N) {
vector<vector<int>> dp(K+1,vector<int>(N+1,0));
for(int n = 0;n < N+1;n++){
dp[1][n] = n;
}
for(int k = 0;k < K+1;k++){
dp[k][1] = 1;
}
// 构建动态规划数组
for(int k = 2;k < K+1;k++){
for(int n = 2; n < N+1;n++){
int tmpres = N;
for(int x = 1;x <= n;x++){
int tmpmax = max(dp[k-1][x-1],dp[k][n-x]);
tmpres = min(tmpres, 1 + tmpmax);
}
dp[k][n] = tmpres;
}
}
return dp[K][N];
}
};
时间复杂度:
O
(
K
N
2
)
{O(KN^2)}
O(KN2) 空间复杂度:
O
(
K
N
)
{O(KN)}
O(KN)
可以进一步降低时间和空间复杂度