题目

题目链接

你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N  共有 N 层楼的建筑。
每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去,如果没有碎可以继续使用。
你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。
每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层 X 扔下(满足 1 <= X <= N)。
你的目标是确切地知道 F 的值是多少。
无论 F 的初始值如何,请你确定 F 的值的最小移动次数是多少?

例如:

输入:K = 1, N = 2
输出:2
输入:K = 2, N = 100
输出:14
输入:K = 3, N = 14
输出:4
注意
  • 1 <= K <= 100
  • 1 <= N <= 10000

思路

算法一

(动态规划)$O(K\!N)$

  1. 状态$f(i,j)$表示使用$i$个鸡蛋,最大楼层为$j$时,所需要的最小移动次数。
  2. 显然初始状态$f(1,j)=j$。对于状态$f(i,j)$,如果枚举上一次测试为楼层$s$,则可以得到如下转移$f(i,j) = min_{s=1}^j(max(f(i-1,s-1),f(i,j-s)) + 1)$,分别表示在第$s$层摔碎和没摔碎。
  3. 如果直接枚举$s$,则总的时间复杂度为$O(K\!N^2)$,无法通过。考虑$f(i-1,s-1)和f(i,j-s)$的大小关系,可以发现,前者随着$s$单调递增,后者单调递减,且每次变化的值最多为1(可证明,略)。所以,如果存在${s}'$使得$f(i-1,s-1) = f(i,j-s)$,则此时${s}'$就是最优的;否则取两者最相近的两个$s$作比较,取最小值。
  4. 至此,$s$可以二分解决;总的时间复杂度:$O(K\!N\!logN)$。
  5. 但进一步可以发现,$s$会随着$j$的增加而增加,即最优决策点${s}'$是随着$j$单调递增的。因为对于固定的$s$,$f(i,j-s)$会随着$j$而增加,这就会造成3中的最优决策点也会向后移动。所以,我们只需在每次移动$j$后,继续从上次的${s}'$向后寻找最优决策点即可。
  6. 最终答案是$f(K,N)$

注意:在鸡蛋没摔碎时,我们还能用这$i$个鸡蛋在在上面的$j-s$层确定$F$,这里的实验与在第$1~(j-w)$所需的次数是一样的,因为它们的实验方法和步骤都是相同的,只不过这$(j-w)$层在上面罢了。

时间复杂度

  • 状态数为$O(K\!N)$,对于每个$i$,寻找最优决策的均摊时间为$O(N)$,故总时间复杂度为$O(K\!N)$

C++代码

 class Solution {
public:
int superEggDrop(int K, int N) {
int m = K, n = N;
const int maxn = + ;
const int maxm = + ;
int d[maxn][maxm]; //dp[i][j]表示有i颗鹰蛋在j层楼的最少次数
if (m >= ceil(log(n + ) * 1.0) / log(2.0))
return (int)ceil(log((n + ) * 1.0) / log(2.0));
else
{
memset(d, , sizeof(d));
for (int i = ; i <= n; i++) d[][i] = i;
for (int i = ; i <= m; i++)
{
int s = ;
for (int j = ; j <= n; j++)
{
d[i][j] = d[i][j - ] + ; // while (s < j && d[i - ][s] < d[i][j - s - ]) s++; d[i][j] = min(d[i][j], max(d[i - ][s - ], d[i][j - s]) + );
if (s < j) d[i][j] = min(d[i][j], max(d[i - ][s], d[i][j - s - ]) + );
}
}
return d[m][n];
}
}
};

算法二

(动态规划)$O(KlogN)$

  1. 状态$f(i,j)$表示进行$i$次移动,有$j$个鸡蛋,最多可以检查的楼层高度是多少。
  2. 初始状态是$f(1,0)=0$,$f(1,j),j \geq 1$。
  3. 先给出转移方程,$f(i,j)= f(i-1,j-1)+f(i-1,j)+1$。假设$n_1=f(i-1,j-1),n_2=f(i-1,j)$,我们在第$i$次移动时测试第$n_1+1$层。
  4. 如果测试时鸡蛋碎掉了,则我们可以通过$i-1$次移动和$j-1$个鸡蛋来找到最高不会碎掉的楼层,因为楼层不会超过$n_1$了;如果鸡蛋没有碎掉,则在此基础上,我们可以使用$i-1$次移动和$j$个鸡蛋,在继续向上检查$n_2$层,故答案在$\left [ 0, n_1 + n_2 + 1 \right ]$范围内,都可以通过$i$次移动、$j$个鸡蛋来找到。
  5. 返回最小的$m$满足,$f(m,K) \geq N$。
  6. 这里第一维可以省略,更新时只需要倒序更新即可。

时间复杂度

  • 最多进行$logN$轮更新,每轮更新需要$O(K)$的时间,故时间复杂度$O(K\!logN)$。

C++代码

 class Solution {
public:
int superEggDrop(int K, int N) {
vector<int> f(K + , );
f[] = ;
int m = ;
while (f[K] < N) {
for (int i = K; i >= ; i--)
f[i] = f[i] + f[i - ] + ;
m++;
} return m;
}
};

在URAL OJ上也有这题,只是数据范围有所不同:Chernobyl’ Eagle on a Roof

参考链接:

1、https://www.acwing.com/solution/leetcode/content/579/

2、朱晨光:《优化,再优化!——从《鹰蛋》一题浅析对动态规划算法的优化

LeetCode887鸡蛋掉落——dp的更多相关文章

  1. 1. 线性DP 887. 鸡蛋掉落 (DP+二分)

    887. 鸡蛋掉落 (DP+二分) https://leetcode-cn.com/problems/super-egg-drop/ /*首先分析1个蛋,1个蛋的话,最坏情况需要N次,每次只能从0 1 ...

  2. [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 ...

  3. 记录Leetcode 鸡蛋掉落 的思路

    前言 首先看一下这个题目,是Leetcode的第887题"鸡蛋掉落": 你将获得 `K` 个鸡蛋,并可以使用一栋从 `1` 到 `N` 共有 `N` 层楼的建筑. 每个蛋的功能都是 ...

  4. Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)

    887. 鸡蛋掉落 你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑. 每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去. 你知道存在楼层 F ,满足 0 < ...

  5. 动态规划法(六)鸡蛋掉落问题(一)(egg dropping problem)

      继续讲故事~~   这天,丁丁正走在路上,欣赏着路边迷人的城市风景,突然发现前面的大楼前围了一波吃瓜群众.他好奇地凑上前去,想一探究竟,看看到底发生了什么事情.   原来本市的一位小有名气的科学家 ...

  6. LeetCode 887.鸡蛋掉落(C++)

    每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去. 你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的 ...

  7. [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 ...

  8. 奇妙的算法【11】LeetCode-专属算法面试题汇总

    这个是LeetCode上面的编程训练专项页面,地址:https://leetcode-cn.com/explore/interview/card/top-interview-quesitons-in- ...

  9. 2018年第九届蓝桥杯【C++省赛B组】B、C、D、F、G 题解

    B. 明码 #STL 题意 把每个字节转为2进制表示,1表示墨迹,0表示底色.每行2个字节,一共16行,布局是: 第1字节,第2字节 第3字节,第4字节 .... 第31字节, 第32字节 给定一段由 ...

随机推荐

  1. action 与 action 之间的跳转

    这个要看你的两个action是不是在通一个package下了 <!-- 相同package下调用其它action --><action name="loginUser&qu ...

  2. AC自动机简明教程

    不会kmp和Trie树的请点击右上角X. AC自动机与kmp的唯一区别便是从单模式串变成了多模式串. 那么与kmp相同,AC自动机中的fail指针是指向当前状态的最长后缀. 当然这个后缀要在Trie树 ...

  3. bzoj1878 [SDOI2009]HH的项链——树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1878 离线树状数组,巧妙的思路呢: 给每种项链记录一个最后出现的位置lst,根据项链最后出现 ...

  4. h5 页面设计尺寸

    请注意:(以下所有讨论内容和规范均将viewport设定为content=”width=device-width”的情况下) 也就是我们的H5页面前端代码里面必须包含 <meta content ...

  5. window下 node.js 的安装

    下载安装文件 Node.js安装包及源码下载地址为:https://nodejs.org/en/download/. 32 位安装包下载地址 : https://nodejs.org/dist/v4. ...

  6. Ueditor中代码的高亮和背景在前端页面的实现

    首先废话就不多说,这个富文本编辑器的下载和js等基本文件的导入略. 我的最终目标是这样的,我们在页面中的富文本框中输入代码,希望它能够被后台接受.存入数据库,当通过服务器将这些代码再一次显示在前台的页 ...

  7. sql server 改sa 密码

      ALTER LOGIN sa ENABLE ; ALTER LOGIN sa WITH PASSWORD = 'kongwenyi' ;

  8. 升级Python后, yum不能用了

    yum需要使用python2,而升级python3后,就会导致语法错误 更正方法: sudo vim /usr/bin/yum 然后把第一行的python改成python2就好了 之后如果出现类似的, ...

  9. POJ 2833 The Average(优先队列)

    原题目网址:http://poj.org/problem?id=2833 本题中文翻译: 描述 在演讲比赛中,当选手完成演讲时,评委将对他的演出进行评分. 工作人员删除最高成绩和最低成绩,并计算其余成 ...

  10. Django MTV模型思想

    一.Django的MTV分别代表: 1.Model(模型):负责业务对象与数据库的对象(ORM) 2.Template(模版):负责如何把页面展示给用户 3.View(视图):负责业务逻辑,并在适当的 ...