这是经典的扔鸡蛋的题目。 同事说以前在uva上见过,不过是扔气球。题意如下:

题意:

你有K个鸡蛋,在一栋N层高的建筑上,被要求测试鸡蛋最少在哪一层正好被摔坏。

你只能用没摔坏的鸡蛋测试。如果一个鸡蛋在上一次测试中没有被摔坏,那么你可以重复使用,否则,你只能用下一个鸡蛋。

需要求,最小的步数,使得你在这么多步内一定测试出结果。

思路:

O(K * N^2)

首先,这个题比较绕。需要求一个最优决策使得步数最小,但是实际的步数是随着真实结果变化而变化的。

于是,为了保证在我们假设的步数内一定能够解完,我们可以假设每次决策都会得到最坏结果。

dp[n][k] 表示用k个鸡蛋测n层最少需要多少步。

我们可以枚举第一次在第i层扔鸡蛋,会得到两种结果:

  1. 鸡蛋坏掉: 我们接下来需要面对的情形是: 用 k-1 个鸡蛋来测量 i-1 层,所以最少需要 dp[i-1][k-1] 步。
  2. 鸡蛋没坏: 我们接下来要面对的情形是: 用 k 个鸡蛋来测量 n-i 层,所以最少需要 dp[n-i][k] 步。

    因为我们总会面对最坏情况,所以,在第i层扔,会用 max(dp[i-1][k-1], dp[n-i][k]) + 1 步。

所以我们的递推式如下:

dp[n][k] = min{ max(dp[i-1][k-1], dp[n-i][k]) + 1 } (1 <= i <= n)

代码:

const int MAXK = 100, MAXN = 100;

int max(int a, int b) {return a > b ? a : b;}
int min(int a, int b) {return a < b ? a : b;} int superEggDrop(int K, int N) {
int dp[MAXN+2][MAXK+2];
for (int i = 0; i <= MAXN; i++) {
dp[i][0] = 0;
dp[i][1] = i;
}
for (int j = 2; j <= MAXK; j++) {
for (int i = 1; i <= MAXN; i++) {
dp[i][j] = i;
for (int k = 1; k < i; k++) {
dp[i][j] = min(dp[i][j], max(dp[k-1][j-1], dp[i-k][j]) + 1);
}
}
}
return dp[N][K];
}

思路: O(K * logN)

我们可以改变一下求解的思路,求k个鸡蛋在m步内可以测出多少层:

假设: dp[k][m] 表示k个鸡蛋在m步内最多能测出的层数。

那么,问题可以转化为当 k <= K 时,找一个最小的m,使得dp[k][m] <= N。

我们来考虑下求解dp[k][m]的策略:

假设我们有k个鸡蛋第m步时,在第X层扔鸡蛋。这时候,会有两种结果,鸡蛋碎了,或者没碎。

如果鸡蛋没碎,我们接下来会在更高的楼层扔,最多能确定 X + dp[k][m-1] 层的结果;

如果鸡蛋碎了,我们接下来会在更低的楼层扔,最多能确定 Y + dp[k-1][m-1] 层的结果 (假设在第X层上还有Y层)。

因此,这次扔鸡蛋,我们最多能测出 dp[k-1][m-1] (摔碎时能确定的层数) + dp[k][m-1] (没摔碎时能确定的层数) + 1 (本层) 层的结果。

另外,我们知道一个鸡蛋一次只能测一层,没有鸡蛋一层都不能测出来。

因此我们可以列出完整的递推式:

dp[k][0] = 0

dp[1][m] = m (m > 0)

dp[k][m] = dp[k-1][m-1] + dp[k][m-1] + 1 (k > 0, m>0)

代码:

// NOTE: 第一维和第二维换了下位置
int superEggDrop(int K, int N) {
int dp[N+2][K+2];
memset(dp, 0, sizeof(dp));
dp[0][0] = 0;
for (int m = 1; m <= N; m++) {
dp[m][0] = 0;
for (int k = 1; k <= K; k++) {
dp[m][k] = dp[m-1][k] + dp[m-1][k-1] + 1;
if (dp[m][k] >= N) {
return m;
}
}
}
return N;
}

Leetcode 887 Super Egg Drop(扔鸡蛋) DP的更多相关文章

  1. [LeetCode] 887. 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 iden ...

  2. LeetCode 887. Super Egg Drop

    题目链接:https://leetcode.com/problems/super-egg-drop/ 题意:给你K个鸡蛋以及一栋N层楼的建筑,已知存在某一个楼层F(0<=F<=N),在不高 ...

  3. Coursera Algorithms week1 算法分析 练习测验: Egg drop 扔鸡蛋问题

    题目原文: Suppose that you have an n-story building (with floors 1 through n) and plenty of eggs. An egg ...

  4. 【LeetCode】887. Super Egg Drop 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 参考资料 日期 题目地址:https://leetc ...

  5. 887. 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 ident ...

  6. [Swift]LeetCode887. 鸡蛋掉落 | 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 ident ...

  7. [CareerCup] 6.5 Drop Eggs 扔鸡蛋问题

    6.5 There is a building of 100 floors. If an egg drops from the Nth floor or above, it will break. I ...

  8. 扔鸡蛋问题具体解释(Egg Dropping Puzzle)

    经典的动态规划问题,题设是这种: 假设你有2颗鸡蛋,和一栋36层高的楼,如今你想知道在哪一层楼之下,鸡蛋不会被摔碎,应该怎样用最少的測试次数对于不论什么答案楼层都可以使问题得到解决. 假设你从某一层楼 ...

  9. 扔鸡蛋问题详解(Egg Dropping Puzzle)

    http://blog.csdn.net/joylnwang/article/details/6769160 经典的动态规划问题,题设是这样的:如果你有2颗鸡蛋,和一栋36层高的楼,现在你想知道在哪一 ...

随机推荐

  1. js获取单独一个checkbox是否被选中

    <script language=javascript> function check(){ var xz=document.getElementById("xz"); ...

  2. Java 判断中文字符

    Java判断一个字符串中是否有中文字符有两种方法,但是原理都一样,就是通过Unicode编码来判断,因为中文在Unicode中的编码区间为:0x4e00--0x9fa5 第一种: String chi ...

  3. WebView 用法总结

    1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出 Web page not available 错误. ...

  4. Bayesian Regression

    Thus we see that there are very close similarities between this Bayesian viewpoint and the conventio ...

  5. fsockopen get,post 封装 (转)

    function http_request($url, $method = 'GET', $postfields = NULL, $headers = array()) {   $parse = pa ...

  6. [Apple开发者帐户帮助]二、管理你的团队(5)转移帐户持有人角色

    组织团队的帐户持有人可以将帐户持有人角色转移给团队中的其他人.如果您是个人注册并需要将您的会员资格转移给其他人,请与我们联系. 所需角色:帐户持有人. 转移Apple Developer Progra ...

  7. HDU1043 Eight

    题目: 简单介绍一下八数码问题:        在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8           在上图中,由于右下角位置是空的 ...

  8. Hadoop一主一从部署(2)

    Hadoop部署一主一从(2) 1.关闭防火墙和Linux守护进程 执行命令: iptables -F setenforce 0 2.对Hadoop集群进行初始化,在namenode(主机)上执行命令 ...

  9. python重定向原理及实例

    1. 前言 为了在Python编程中, 利用控制台信息, 我们需要对控制台输出进行接管(重定向).在Python中,控制台输出的接口是sys.stdout,通过分析print与sys.stdout之间 ...

  10. 【Codeforces】Codeforces Round #373 (Div. 2) -C

    C. Efim and Strange Grade Efim just received his grade for the last test. He studies in a special sc ...