引入

2个鸡蛋,从100层楼上往下扔,以此来测试鸡蛋的硬度。比如鸡蛋在第9层没有摔碎,在第10层摔碎了,那么鸡蛋不会摔碎的临界点就是9层。

问:如何用最少的尝试次数,测试出鸡蛋不会摔碎的临界点?

分析

注意:题目的一个隐含在该最少次数下,一定能测出。

完美解决这个问题的思路是先逆向假设存在一个最优解x,第一次就应该从x层开始扔。为什么要从第x层开始扔呢?

假设第一次扔在第x+1层:如果第一个鸡蛋碎了,那么第二个鸡蛋只能从第1层开始一层一层扔,一直扔到第x层。这样一来,我们总共尝试了x+1次,和假设尝试x次相悖。由此可见,第一次扔的楼层必须小于x+1层。

假设第一次扔在第x-1层:如果第一个鸡蛋碎了,那么第二个鸡蛋只能从第1层开始一层一层扔,一直扔到第x-2层。这样一来,我们总共尝试了x-2+1 = x-1次,和假设尝试x次同样

假设第一次扔在第x层:如果第一个鸡蛋碎了,那么第二个鸡蛋只能从第1层开始一层一层扔(因为这是最后一个鸡蛋了,所以不能再冒险隔着楼层扔了),一直扔到第x-1层。这样一来,我们总共尝试了x-1+1 = x次,刚刚好没有超出假设次数。

接下来第二次该如何扔呢?首先明确,扔第一次的结果有两种,一是鸡蛋碎了,那么接下来从第一层开始往上扔。二是鸡蛋没碎,因为总共要扔x次,之前已经扔了一次,所以接下来就还要扔x-1次,那么问题就转变成了在100-x层高的楼上,最少扔x-1次该如何扔了。按照相同的思路,就在x-1层扔咯,这里的x-1对应就是实际的x+(x-1)层。按照这个思路一直重复操作,最后一次扔的层数应该是第100层,于是就有了如下的关系式。

x+(x-1)+(x-2)+...+1=100

共有x项,解出来x等于14,这便是最终的答案。

正题

N个鸡蛋和M层楼,要找到鸡蛋摔不碎的临界点,需要尝试几次?

分析

假设dp[N][M]等于最坏的运气下最多需要测试的次数,我们第一次扔在x层,那么有两种可能,若鸡蛋碎了,那么有dp[N][M]=dp[N-1][x-1]+1,若鸡蛋没碎,dp[N][M]=dp[N][M-x]+1。我们想求的是“运气最差”情况下,即在最优方案下最多需要测试的次数,所以dp[N][M]应该等于max(dp[N-1][x-1]+1,dp[N][M-x]+1)。而注意,x是一个不确定的数,它的取值范围为(0<=x<=M),x的取值决定了方案的优劣,若要方案最优,则需取最恰当的x值,即能令dp[N][M]最小,所以有

dp[N][M]=min{max(dp[N-1][x-1]+1,dp[N][M-x]+1) | 0<=x<=M}

上面的方程即为动态规划所需要的状态转移方程。

完整解题代码

#include<iostream>
#include<algorithm>
using namespace std;//N个鸡蛋,M层楼
void solve(int N,int M){if(N<1||M<1)  return;//   定义记忆数组int dp[N+1][M+1];// 初始化记忆数组,令其等于其楼层数 for(int i=1;i<=N;i++){for(int j=1;j<=M;j++){dp[i][j]=j;}}for(int i=2;i<=N;i++){for(int j=2;j<=M;j++){int tmp=dp[i-1][j];for(int x=1;x<=j;x++){
//              tmp存放1至x层时的最优方案次数 tmp=min(tmp,max(dp[i-1][x-1]+1,dp[i][j-x]+1));         }dp[i][j]=tmp;}}cout<<dp[N][M]<<endl;
}int main(){solve(2,100);return 0;
}

优化

要得到第N个鸡蛋时的答案,其实只需要找到N-1个鸡蛋时的情况,不需要把第一个鸡蛋到第N个鸡蛋时的情况全部记录,所以记忆数组自需申请dp[2][M+1]的空间即可。这样可以降低空间复杂度。

同类型题目:测试次数

x星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机。
各大厂商也就纷纷推出各种耐摔型手机。x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后才允许上市流通。

x星球有很多高耸入云的高塔,刚好可以用来做耐摔测试。塔的每一层高度都是一样的,与地球上稍有不同的是,他们的第一层不是地面,而是相当于我们的2楼。

如果手机从第7层扔下去没摔坏,但第8层摔坏了,则手机耐摔指数=7。特别地,如果手机从第1层扔下去就坏了,则耐摔指数=0。如果到了塔的最高层第n层扔没摔坏,则耐摔指数=n。

为了减少测试次数,从每个厂家抽样3部手机参加测试。

某次测试的塔高为1000层,如果我们总是采用最佳策略,在最坏的运气下最多需要测试多少次才能确定手机的耐摔指数呢?

请填写这个最多测试次数。

注意:需要填写的是一个整数,不要填写任何多余内容。

分析

这是第九届蓝桥杯的题目,基本是换了一个马甲,思路和扔鸡蛋问题是一模一样的。如果做过扔鸡蛋的题目,那么肯定可以很块做出来,可惜我没有。。。

完整解题代码

#include<iostream>
#include<algorithm>
using namespace std;int main(){
//  3个手机,1000层楼,存储对应的测试次数 int dp[4][1001];
//  初始化记忆数组 for(int i=0;i<4;i++){for(int j=1;j<=1000;j++){dp[i][j]=j;}}// for(int i=1;i<4;i++){for(int j=1;j<=1000;j++){
//          tmp暂存1至x层时的最优方案次数,初始化值为第i-1个手机,j层楼时的测试次数 int tmp=dp[i-1][j];for(int x=1;x<=j;x++){tmp=min(tmp,max(dp[i-1][x-1]+1,dp[i][j-x]+1));}dp[i][j]=tmp;}}cout<<dp[3][1000]<<endl;
} 

运行结果是13。

本文参考了以下两篇微信推送

  1. 漫画:有趣的扔鸡蛋问题

  2. 漫画:动态规划解决扔鸡蛋问题

动态规划之扔鸡蛋(或手机)问题相关推荐

  1. [数据结构与算法]动态规划:扔鸡蛋问题

    参考链接:https://gitee.com/lambertcao/fucking-algorithm/blob/master/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92 ...

  2. java动态规划鸡蛋问题_动态规划——楼层扔鸡蛋问题

    前言 大一的时候蓝桥杯省赛遇到过(作为非编程题的压轴题),这次看的别人的面经也多次出现,就写篇博文总结一下. 题目 有一栋楼共100层,一个鸡蛋从第N层及以上的楼层落下来会摔破, 在第N层以下的楼层落 ...

  3. 一道关于扔球/扔鸡蛋/摔手机的DP问题(蓝桥杯题目/面试题)

    注:问题的解决感谢广东技术师范学院林智勇老师的指导 (一)问题描述 给定N层楼和i个球.用i个球检测在这N层楼中的某一层t球扔下楼时不碎,而在t+1层球扔下楼时会碎,则t层称为最高安全层.求用i个球一 ...

  4. java动态规划鸡蛋问题_教你彻底理解动态规划——扔鸡蛋问题 Drop Eggs2

    问题 有一个n层的建筑.如果一个鸡蛋从第k层及以上落下,它会碎掉.如果从低于这一层的任意层落下,都不会碎. 有m个鸡蛋,用最坏的情况下实验次数最少的方法去找到k, 返回最坏情况下所需的实验次数. 样例 ...

  5. 动态规划与数学方程法解决楼层扔鸡蛋问题

    1.问题描述 两个软硬程度一样的鸡蛋,它们有可能都在一楼就摔碎,也可能从一百层楼摔下来没事.有座100层的建筑,用这两个鸡蛋确定哪一层是鸡蛋可以安全落下的最高位置,可以摔碎两个鸡蛋,求给出一个最佳策略 ...

  6. 谷歌面试题之扔鸡蛋的问题(蓝桥杯摔手机的问题)

    来自一个古老的公众号(摔手机就是根据扔鸡蛋过来的) 吐个槽先 正如昨天所说,这道题据说它最早见于谷歌的某次面试,由于题目表述容易,而解答相对麻烦,于是被很多人采用,广泛见于一些算法.规划的面试里. 要 ...

  7. 彻底搞懂-扔鸡蛋问题-方程-动态规划

    1.题目: 2个鸡蛋,从100层楼上往下扔,以此来测试鸡蛋的硬度,比如鸡蛋在第9层没有摔碎而在第10层摔碎了,那么鸡蛋不会摔碎的零界点就是9层,如何用最少的尝试次数,测试出鸡蛋不会摔碎的临界点? 2. ...

  8. 高楼扔鸡蛋问题-经典动态规划

    文章目录 1. 高楼扔鸡蛋 2. 猜数字大小 1. 高楼扔鸡蛋 给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑. 已知存在楼层 f ,满足 0 <= f &l ...

  9. 高楼扔鸡蛋问题 - 动态规划+反推演绎

    对于高楼扔鸡蛋问题,本文尝试反其道而行之:首先描述一个普适的高楼扔鸡蛋问题,然后利用动态规划法解决扔鸡蛋次数的问题,最后由获取次数的答案反推出扔鸡蛋的方法. 这种由次数答案反推出方法的演绎方式令人有点 ...

最新文章

  1. pycharm中导出依赖包 在pycharm下边的Terminal打开命令行终端执行命令
  2. Microsoft Dynamics CRM 2011 相关-摘自网络
  3. a*算法流程图_学好流程控制结构轻松应对高考数学程序算法题
  4. 在项目里交叉使用Swift和OC
  5. 20145202马超 2016-2017-2 《Java程序设计》第一次实验
  6. 使用 Bridge to Kubernetes 简化云端开发
  7. 哈工大人工智能研究院院长刘劼:AIoT 核心在“智”不在“联”,需云边端协同...
  8. java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.String
  9. HDU 6446 Tree and Permutation(赛后补题)
  10. 蓝桥杯 BASIC-14 基础练习 时间转换
  11. AD15实际工程的基本操作
  12. 打印机扫描计算机远程扫描仪,怎么用打印机扫描文件-彩色网络打印机扫描设置FTP版...
  13. 2014网络红人斌少网络红人彭伟个人资料
  14. MySQL常用语句(二)
  15. Java基础之二维数组
  16. 遇到问题---thrift--python---ImportError: No module named thrift
  17. linux7配置dns服务,RHEL7 DNS配置
  18. java获取jira上的任务
  19. 宜家app android,IKEA宜家家居下载
  20. python下载谷歌地图瓦片_python抓取天地图瓦片

热门文章

  1. NTFS - 获取NTFS系统格式的盘符
  2. postgresql源码学习(45)—— PostmasterMain(2) GUC参数简介及设置
  3. 如何利用无常损失从流动资金池中提取价值
  4. 报错“FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disa”
  5. “F5G+EIoT“构建能源物联网,助力电力物联网数据服务
  6. 加速乐的欢乐破解与__jsl_clearance的生成
  7. GetLastError 返回码含义
  8. tkinter简明教程
  9. Tomcat报ClassFormatException: Invalid byte tag in constant pool: 19解决方法
  10. 比尔总动员比尔座驾获取攻略