扔鸡蛋问题-方程-动态规划
参考:程序员小灰
https://blog.csdn.net/weixin_40564421/article/details/78988078
题目:2个鸡蛋,从100层楼上往下扔,以此来测试鸡蛋的硬度,比如鸡蛋在第9层没有摔碎而在第10层摔碎了,那么鸡蛋不会摔碎的零界点就是9层,如何用最少的尝试次数,测试出鸡蛋不会摔碎的临界点?
最笨法:把其中一个鸡蛋从第1层开始往下扔,如果第1层没碎换到第2层扔,如果第2层没碎换到第3层扔,,,如果第59层没碎换到第60层扔,如果第60层碎了,说明不会摔碎的临界点是59层,最坏情况下需要扔100次
二分法:把鸡蛋从50层往下扔,如果第一枚在50层碎了,就从第1层开始(一共只有两个鸡蛋,第一个鸡蛋碎了,第二个鸡蛋就只能用最保守的方式一层一层扔,假如第二个鸡蛋从25层扔,碎了,就无法判断临界点了);如果没碎,继续使用二分法,在剩余楼层的一半(75层)往下扔,,,,最坏需要尝试50次
平方根法:做一个平方运算,100的平方根是10,因此我们尝试每10层扔一次,第一次从10层扔,第二次从20层扔,第三次从30层,,,一直到100层,最好情况是在第10层碎掉,尝试次数为1+9=10次;最坏情况是在第100层碎掉,尝试次数为10+9=19次
方程法:将思路逆转
假设问题存在最优解,这个最优解的最坏情况尝试次数是x次,那么我们第一次扔鸡蛋该选择哪一层?
答案是从第x层开始,选择更高一层或更第一层都不合适
分析:假设第一次扔在第x+1层,如果第一个鸡蛋碎了,那么第二个鸡蛋只能从第1层一层一层扔,一直到第x层,这样总共扔了x+1次,和假设尝试x次相悖,由此可见,第一次扔的楼层必须小于x+1次
假设第一次扔在第x-1层,如果第一个鸡蛋碎了,那么第二个鸡蛋开始一层一层扔,直到第x-2层,这样我们总共扔了x-1次,虽然没有超过假设次数,但似乎有些过于保守(什么意思,还没理解)
假设第一次扔在第x层,如果第一个鸡蛋碎了,那么第二个鸡蛋开始一层一层扔,一直到第x-1层,共x次
因此要向尽量楼层跨度大一些,又保证不超过假设的尝试次数x,那么第一次扔鸡蛋的最优选择就是第x层
更进一步。。。
如果第一次扔鸡蛋在第x层,但并没有打碎,第二次扔鸡蛋在哪一层?
如果第一次扔鸡蛋没碎,我们的尝试次数消耗了一次,问题就转为,两个鸡蛋在100-x层楼往下扔,要求尝试次数不得超过x-1次,则第二次尝试的楼层跨度为x-1层,绝对楼层是x+x-1层;如果还没碎,第三层楼层跨度是x-2,第四层是x-3!
so,x+(x-1)+(x-2+...+1=100,左边多项式是各次扔鸡蛋的楼层跨度之和,假设尝试x次,所以该多项式共有x项,右边是总的楼层数100,解方程可得x=14((x+1)*x/2=100)
因此,最优解在最坏情况的尝试次数是14次,第一次扔鸡蛋的楼层也是14层,在第一个鸡蛋没碎的情况下,尝试的楼层为:14,27,39,50,60,69,77,84,90,95,99,100,假如鸡蛋不会碎临界点在65层,那么依次:14,27,50,60,69碎了,让后第二个鸡蛋从61层开始61,62,63,64,65,66碎了,即不会碎的临界点是65层
动态规划解题:有M层楼N个鸡蛋,找到鸡蛋摔不碎的临界点,需要尝试几次?
可以把m层楼和n个鸡蛋的问题转化为一个函数F(m,n),其中楼层数m和鸡蛋数n是函数的两个参数,函数的值则是最优解的最大尝试次数,假设第一个鸡蛋扔出的位置在第x层(1<=x<=m),会出现两种情况:
1.第一个鸡蛋没碎,则剩余m-x层楼和n个鸡蛋,F(m-x,n)+1
2.第一个鸡蛋碎了,则从1到x-1层尝试,剩余鸡蛋n-1,F(x-1,n-1)+1
so,我们要求m层楼n个鸡蛋条件下,最大尝试次数的最小解,即
F(m,n)= Min(Max(F(m-x,n)+1,F(x-1,n-1)+1)) . 1<=x<=m
eg:3个鸡蛋,4层楼
首先填充第一个鸡蛋在各个楼层的尝试次数,以及任意多鸡蛋在1层楼的尝试次数,原因:只有一个鸡蛋,so只能从1层扔到最后一层,尝试次数为楼层数量;只有一个楼层,无论有几个鸡蛋,也只有一种扔法,尝试次数只能为1
2个鸡蛋2层楼,带入状态转移方程式F(2,2)=Min( Max(F(2-x,2)+1,F(x-1,2-1)+1)) )
x可以为1和2,so:
x=1时,F(2,2)=Max(F(2-1,2)+1,F(1-1,2-1)+1))=Max(F(1,2)+1, F(0,1)+1)=Max(1+1, 0+1)=2
x=2时, F(2,2)=Max(F(2-2,2)+1,F(2-1,2-1)+1))=Max(F(0,2)+1, F(1,1)+1)=Max(0+1, 1+1)=2
取最小值即为2
依次类推
先上代码(当然了,还是别人写的,看的可真费劲,话说动态规划看一次不懂一次。。。)
package CSDN;public class Egg {public static int getMinSteps(int eggs,int floors){if(eggs<1 || floors<1){return 0;}
// 第一步,创建动态规划的备忘录,即状态转移矩阵int [][]state=new int[eggs+1][floors+1];
// 第二步,考虑边界
// 先考虑eggs边界,eggs为0,则为0;eggs为1,肯定从第0层往上依次实验for(int i=1;i<=floors;i++){state[0][i]=0;state[1][i]=i;}
// 再考虑floor的边界,floors为0即为0,floors为1即为1for(int i=1;i<=eggs;i++){state[i][0]=0;state[i][1]=1;}
// 第三步就是状态方程了,鸡蛋从第2个开始算,楼层也从第2开始算for(int egg=2;egg<=eggs;egg++){for(int floor=2;floor<=floors;floor++){
// 你还有egg个鸡蛋,一共有floor层楼的子问题
// 定义一个变量来存储最终结果,找到在哪里扔能达到所扔次数最少的目标int result=Integer.MAX_VALUE;
// 从第drop层扔鸡蛋for(int drop=1;drop<=floor;drop++){
// 碎了,剩下的问题即如何在drop-1层,用egg-1个鸡蛋寻找最优解int broken=state[egg-1][drop-1];
// 没碎,在floors-drop层,用egg个鸡蛋找最优解int unbroken=state[egg][floor-drop];
// 两种情况取最大值,因为我根本不知道鸡蛋会不会碎int condition=Math.max(broken, unbroken)+1;
// 不断和上一次结果做比较,得到最少的扔次数result=Math.min(condition, result);}state[egg][floor]=result;}}
// 以上步骤在不断的往状态举证填充,到这里已经填充完毕return state[eggs][floors];} public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(getMinSteps(2,100));System.out.println(getMinSteps(2,39));System.out.println(getMinSteps(3,39));}}
测试下
14
9
6
扔鸡蛋问题-方程-动态规划相关推荐
- 彻底搞懂-扔鸡蛋问题-方程-动态规划
1.题目: 2个鸡蛋,从100层楼上往下扔,以此来测试鸡蛋的硬度,比如鸡蛋在第9层没有摔碎而在第10层摔碎了,那么鸡蛋不会摔碎的零界点就是9层,如何用最少的尝试次数,测试出鸡蛋不会摔碎的临界点? 2. ...
- 高楼扔鸡蛋问题-经典动态规划
文章目录 1. 高楼扔鸡蛋 2. 猜数字大小 1. 高楼扔鸡蛋 给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑. 已知存在楼层 f ,满足 0 <= f &l ...
- 动态规划之扔鸡蛋(或手机)问题
引入 有2个鸡蛋,从100层楼上往下扔,以此来测试鸡蛋的硬度.比如鸡蛋在第9层没有摔碎,在第10层摔碎了,那么鸡蛋不会摔碎的临界点就是9层. 问:如何用最少的尝试次数,测试出鸡蛋不会摔碎的临界点? 分 ...
- 动态规划与数学方程法解决楼层扔鸡蛋问题
1.问题描述 两个软硬程度一样的鸡蛋,它们有可能都在一楼就摔碎,也可能从一百层楼摔下来没事.有座100层的建筑,用这两个鸡蛋确定哪一层是鸡蛋可以安全落下的最高位置,可以摔碎两个鸡蛋,求给出一个最佳策略 ...
- 高楼扔鸡蛋问题 - 动态规划+反推演绎
对于高楼扔鸡蛋问题,本文尝试反其道而行之:首先描述一个普适的高楼扔鸡蛋问题,然后利用动态规划法解决扔鸡蛋次数的问题,最后由获取次数的答案反推出扔鸡蛋的方法. 这种由次数答案反推出方法的演绎方式令人有点 ...
- 经典动态规划:高楼扔鸡蛋
点击蓝色"五分钟学算法"关注我哟 加个"星标",天天中午 12:15,一起学算法 作者 | labuladong 来源 | labuladong 今天要聊一个很 ...
- 扔鸡蛋问题 动态规划大法
之前有一篇文章"扔鸡蛋问题",写的是指定鸡蛋个数在指定楼层,求最优解.里面列举了二分法.平方根法和解方程法,但是,如果鸡蛋个数和楼层数是待定的,那这三种方法都搞不定了.所以,这里又 ...
- 每日一道算法题:高楼扔鸡蛋问题(动态规划问题)
题目是这样:你面前有一栋从 1 到N共N层的楼,然后给你K个鸡蛋(K至少为 1).现在确定这栋楼存在楼层0 <= F <= N,在这层楼将鸡蛋扔下去,鸡蛋恰好没摔碎(高于F的楼层都会碎,低 ...
- java动态规划鸡蛋问题_教你彻底理解动态规划——扔鸡蛋问题 Drop Eggs2
问题 有一个n层的建筑.如果一个鸡蛋从第k层及以上落下,它会碎掉.如果从低于这一层的任意层落下,都不会碎. 有m个鸡蛋,用最坏的情况下实验次数最少的方法去找到k, 返回最坏情况下所需的实验次数. 样例 ...
最新文章
- 一文梳理视觉Transformer架构进展:与CNN相比,ViT赢在哪儿?
- Matplotlib实例教程(九)热力图
- 在Spring中使用JTA事务管理
- 防火墙(7)——禁止具体协议
- python3的float数精度_Python numpy 浮点数精度问题
- 扫地机器人欠压检测电路_扫地机器人智能家居必备!靠传感器感知外界环境?...
- STM32 - 定时器的设定 - 基础- 02 - Capture/compare channels 和相关设置寄存器 - 和STM32缩写词条解释
- 多个命令执行结果输出到同一个文件(批处理)
- 仿百度文库实现文档在线预览
- 我的vs2010扩展备忘.jpg
- 执行计划:SET AUTOTRACE TRACEONLY
- lzw编码 matlab,LZW编码算法matlab实现.docx
- VTD — 应用于智能驾驶复杂交通场景仿真工具
- icem网格数和节点数_icem如何查看网格数量
- Python语言程序设计 第七周 文件和数据格式化
- hdu5285-wyh2000 and pupil-(染色法二分图判定)
- 你看到的就是真实的吗?
- https://wenku.baidu.com/view/24def725e53a580217fcf
- YouTube 架构学习体会
- 认识自己——我需要发现自己
热门文章
- 取模运算性质_数学与编程——求余、取模运算及其性质 | 学步园
- U8G2库移植到STM32平台上
- 关于服务端工具gs_guc的部分解读
- Possible missing firmware /lib/firmware/i915/kbl_guc_ver9_14.bin for module i915解决办法
- trojan-gamethief.win32.magania.alsz病毒解决方案
- 积分管理系统---系统介绍
- 时间转换 取模(秒转化成分钟) 65秒转为1分5秒
- 计算机专业刊头,浅谈报纸版面在电脑排版中的美学应用
- 春招进行时,当代大学生求职行为大赏
- 【公示】关于举办“元宇宙数字人制作竞赛”的复函