这是经典的扔鸡蛋的题目。 同事说以前在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. 查找存在某字符的文件列表,不包括svn文件

    find . ! -wholename '*.svn*' -print | xargs grep "img" | awk -F ':.' '{print $1}' | uniq

  2. 【Allwinner ClassA20类库分析】4.GPIO类的使用

        从本节起,開始使用ClassA20类库完毕操作外设的功能,请先在https://github.com/tjCFeng/ClassA20下载ClassA20类库. 封装的目的就是简化操作,试想一 ...

  3. javase - 点餐系统

    public class OrderMsg { public static void main(String[] args) throws Exception { /** * 订餐人姓名.选择菜品.送 ...

  4. Android updater-scripts(Edify Script)各函数详细说明【转】

    本文转载自:http://blog.csdn.net/kwuwei/article/details/40616909 这是Android系统来运行updater-scripts的Edify语言的基本介 ...

  5. jquerymobile之collapsible可折叠块标题内容动态显示

    jquery mobile提供了一种可折叠的组件--data-role="collapsible",这种组件可以通过点击折叠块头部来展开/折叠块内的内容,详细组件说明可参考w3cs ...

  6. awk 去重的同时并保持原来的顺序

    #-----------awk.awk------------ {    if(data[$0]++ == 0)        lines[++count] = $0} END {    for (i ...

  7. LA3276

    费用流 这种棋盘模型大概都是网络流吧 首先我们知道棋子之间不会影响到达目标的步数,那么就好做了,枚举终点,然后就是最小权匹配了,因为就是寻找总和最小,然后费用流就行了. #include<bit ...

  8. PCB MS SQL 将字符串分割为表变量(表值函数)

    Create FUNCTION [dbo].[SplitTable]( @s varchar(max), --待分拆的字符串 ) --数据分隔符 ),), col varchar(max)) --建立 ...

  9. CentOS7 搭建Kafka(一)zookeeper篇

    CentOS7 搭建Kafka(一)zookeeper篇 近几年当红小生Kafka备受各路英雄好汉追捧,一点不比老前辈RabbitMQ和ActiveMQ差,因为流行,所以你就得学啊:我这么懒,肯定是不 ...

  10. django-2的路由层(URLconf)

    URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码 ...