鸡蛋掉落
题目描述
你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑。
每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。
你知道存在楼层 F ,满足 \(0<= F <= N\) 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。
每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层 X 扔下(满足 \(1 <= X <= N\))。
你的目标是确切地知道 F 的值是多少。
无论 F 的初始值如何,你确定 F 的值的最小移动次数是多少?
说明
\(1 <= K <= 100\)
\(1 <= N <= 10000\)
示例
输入: K = 2, N = 6
输出: 3
输入:K = 3, N = 14
输出:4
思路
我们可以考虑使用动态规划来做这道题,状态可以表示成 (K, N),其中 K为鸡蛋数,N 为楼层数。当我们从第 X 楼扔鸡蛋的时候:
如果鸡蛋不碎,那么状态变成 (K, N-X),即我们鸡蛋的数目不变,但答案只可能在上方的 N−X 层楼了。也就是说,我们把原问题缩小成了一个规模为 (K, N-X) 的子问题;
如果鸡蛋碎了,那么状态变成 (K-1, X-1),即我们少了一个鸡蛋,但我们知道答案只可能在第 X 楼下方的 X-1层楼中了。也就是说,我们把原问题缩小成了一个规模为 (K-1, X-1)的子问题。
这样一来,我们定义 dp(K, N)为在状态 (K, N)下最少需要的步数。根据以上分析我们可以列出状态转移方程
\[dp(K,N)=1+min(max(dp(K−1,X−1),dp(K,N−X))) \]
代码
//work it right
class Solution {
public:
int superEggDrop(int K, int N) {
vector<vector<int>> dp(K+1,vector<int>(N+1,0));
int eggNUM=K;
int floorNUM=N;
for(int i=1;i<=floorNUM;++i)
dp[1][i]=i;
for (int i = 1; i <= eggNUM; ++i)
dp[i][1]=1;
for(int i=2;i<=eggNUM;i++)
{
for(int j=2;j<=floorNUM;j++)
{
dp[i][j]=j;
for(int x=1;x<j;++x)
dp[i][j]=min(dp[i][j],max(dp[i][x-1],dp[i-1][j-x])+1);
}
}
return dp[K][N];
}
};
时间复杂度:\(\mathcal{O}(KN^2)\)
优化:
\(dp[i][x-1]\)与\(dp[i-1][j-x]\),前者关于\(x\)单调递增,后者关于\(x\)单调递减,两者最大值的最小值应该在两条直线交点上或下。可以采用二分搜索不断搜索这个值
- \(dp[i][mid-1]<dp[i-1][j-mid]\),说明增加的不够多,继续增
- \(dp[i][mid-1]<dp[i-1][j-mid]\),增加的太多了,减下去
- \(dp[i][mid-1]==dp[i-1][j-mid]\),皆大欢喜。没有也不要紧
//work it fast
class Solution
{
public:
int superEggDrop(int K, int N)
{
vector<vector<int>> dp(K + 1, vector<int>(N + 1, 0));
int eggNUM = K;
int floorNUM = N;
for (int i = 0; i <= floorNUM; ++i)
dp[1][i] = i;
for (int i = 1; i <= eggNUM; ++i)
dp[i][1] = 1;
for (int i = 2; i <= eggNUM; i++)
{
for (int j = 2; j <= floorNUM; j++)
{
dp[i][j] = j;
int left=1,right=j-1,mid;
while(left<right)
{
mid=(left+right)/2;
if(dp[i][mid-1]<dp[i-1][j-mid])
left=mid+1;
else if(dp[i][mid-1]>dp[i-1][j-mid])
right=mid-1;
else
left=right=mid;
}
dp[i][j]=1+min(max(dp[i][left-1],dp[i-1][j-left]),max(dp[i][right-1],dp[i-1][j-right]));
}
}
return dp[K][N];
}
};
时间复杂度:\(\mathcal{O}(KNlog_2N)\)

浙公网安备 33010602011771号