这是经典的扔鸡蛋的题目。 同事说以前在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. java 将byte[]转为各种进制的字符串

    public void test() { byte[] bytes = new byte[10000000]; for (int i = 0; i < 10000000; i++) { if ( ...

  2. sharepoint类型转换

    sharepoint学习汇总 http://blog.csdn.net/qq873113580/article/details/20390149 r[col.ColumnName] = GetType ...

  3. 关于FrameBuffer【转】

    本文转载自:http://blog.csdn.net/ganxingming/article/details/764482 一.FrameBuffer的原理 FrameBuffer 是出现在 2.2. ...

  4. C# ListBox 左移、右移、上移、下移

    C# ListBox 左移.右移.上移.下移 2012-11-17 22:53:45|  分类: 技术研讨 |  标签:listbox  |字号 订阅     /// <summary>  ...

  5. AMQP server localhost:5672 closed the connection. Check login credentials: Socket closed

    2016-04-13 09:23:38.755 18850 INFO oslo.messaging._drivers.impl_rabbit [req-fafc8542-9403-4b5a-89d2- ...

  6. JavaScript alert()函数的使用方法

    这里向大家简单介绍一下JavaScript alert()函数的使用,alert--弹出消息对话框,并且alert消息对话框通常用于一些对用户的提示信息. JavaScript alert()函数 a ...

  7. Redis学习笔记(五)- 数据类型之set类型

    Redis 的set是string类型的无序集合.set元素最大可以包含(2的32次方-1)个元素.set的是通过hash table实现的,所以添加,删除,查找的复杂度都是O(1).hash tab ...

  8. 《CSS Mastery》 读书笔记 (1)

    --本笔记中英混合,专业名词尽量不翻译,免得误解,如果不习惯,就不用往下看了,走好不送. 第一章 基础 人类的好奇心总是促使我们捣鼓,捣鼓是最好做有效的学习CSS的方法 In this chapter ...

  9. 关于jquery的clone()和javascript的cloneNode()

    区别: jquery的clone( ),如果是true就是深克隆,把事件都会克隆过去:如果是false,则仅仅克隆的是结构: javascript的cloneNode( ),如果是true,会将子节点 ...

  10. jsp连接MySQL实现登录

    1.下载驱动,并把jar包放到Tomcat的lib目录下 下载连接 2.把jar包添加到项目中 3.登录页面 <%@ page language="java" content ...