扔鸡蛋问题-经典动态规划问题

2024-06-21 21:18

本文主要是介绍扔鸡蛋问题-经典动态规划问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目
一幢 100 层的大楼,给你2个鸡蛋,如果在第 n 层扔下鸡蛋,鸡蛋不碎,那么从第 n-1 层扔鸡蛋,都不碎。这两只鸡蛋一模一样,不碎的话可以扔无数次,且鸡蛋在0层不会碎。设计一种策略能保证可以测出鸡蛋恰好会碎的楼层,且如果该策略是最坏的情况所扔次数最少

一、概述

思维分析
首先我们需要确定最坏情况是什么样子的。
假设n是我们的决定第一次尝试的楼层,第一个鸡蛋从n层开始扔。

如果没有坏,那么我们就可以从[n+1,100]这个区间扔鸡蛋了,这个时候怎么扔就是我们需要考虑的策略。
但是如果运气比较背,鸡蛋坏了_!那么这个时候我们就只有一个鸡蛋了,所以为了满足我们要测出恰好会碎的楼层,我们只能从1楼一直扔到n-1楼。这个时候我们的最坏情况就是n次。
鸡蛋没有坏该怎么选择第二次以及以后扔鸡蛋的策略呢?
由于没有碎,所以第n层对于我们而言和第0层是一样一样的,所以我们不能采用一层一层增加的方式扔鸡蛋!因为有两个鸡蛋,比较任性。下面提出几个合理的假设,然后分析:

增加n层:碎了的话,最坏情况就是我们还要扔2n-n-1+2=n+1次,这个时候最坏情况比第一次还坏,而且照这个趋势下去,最坏情况只会越来越坏,是不可控的,所以这种策略抛弃。
增加大于n层:和增加n层一样,如果第一个鸡蛋碎了那最坏情况就是越来越坏,且比增加n层更坏(可以自己做个简单的算术推导一下)。
增加小于n层:随着n的不断减小,最坏情况下需要仍的次数恒定为n是不会变的(因为第一次就碎了,对于这种情况就是最坏情况)。那么我们需要考虑的是如何使扔的次数最少,想想看,果断取n-1,这样既保证了快速找到刚好碎的楼层,又保证了最坏情况扔的次数最少。
所以我们最后的策略是增加n-1层。
以上就是一个分析过程,对于第三次,第四次….都可以递归的进行分析。
由于最好情况是第一个鸡蛋一直扔到了100层,而100层与n之间是有一个函数关系的,下面就可以列出一个等式:
n+(n-1)+(n-2)+…+1=100=n(n+1)/2
所以n约等于14
所以第一次从第十四层开始扔,最坏情况就是第一次就碎了,然后需要从1楼开始一层一层的扔,共扔14次。

二、编程实现

import java.util.Scanner;public class Main {//(1)动态规划法:  该算法的空间复杂度是O(nk),时间复杂度是O(nk^2) n表示鸡蛋数,k代表楼层数public static int  dropEggs(int eggs,int floors) {//第一步永远是创建动态规划的备忘录,也叫状态转移矩阵//记住:二维数组里的length是0-start的,又因为包含层数为0或鸡蛋为0的情况,所以定义行高和列宽的时候自然要加1int[][]dp=new int[eggs+1][floors+1];//第二步永远是考虑边界,也就是初始化动态规划的备忘录//先考虑eggs的边界for(int i=0;i!=floors+1;i++) {//首先是eggs=0的情况dp[0][i]=0;//然后是eggs=1的情况//eggs=1的时候,肯定是从第0层一直往上实验dp[1][i]=i;}//再考虑floors的边界for(int i=1;i!=eggs+1;i++) {//首先是floors=0的情况dp[i][0]=0;//然后是floors=1的情况dp[i][1]=1;}//第三步就是状态方程了//找递推过程中的两个紧邻步骤之间的关系,如何由子结果得到母结果//首先,鸡蛋要从2个开始算,因为0个和1个情况你已经考虑完了for(int egg=2;egg!=eggs+1;egg++) {//楼层有多高要从2层起步,因为0层和1层的情况你也考虑完了for(int floor=2;floor!=floors+1;floor++) {//看这里!这里就是你还有egg个鸡蛋,一共有floor层的子问题!//这里定义一个变量来存储最终结果,找到在哪层扔能达到所扔次数最少的目标int result=Integer.MAX_VALUE;for(int drop=1;drop!=floor+1;drop++) {//这里!就是在当前子问题中,你从第drop层扔鸡蛋的情况!//第一种情况,哎呀~碎了!那么剩下的问题就转化成了如何在drop-1层,用egg-1个鸡蛋寻找最优int broken=dp[egg-1][drop-1];//第二种请看,卧槽~没碎!问题就转化成了如果再floos-drop层,用egg个鸡蛋寻找最优解int unbroken=dp[egg][floor-drop];//两种情况我肯定要取最大值,因为我根本不确定鸡蛋会不会碎,我特么又不是先知int condition=Math.max(broken, unbroken)+1;//不断的和上一次的结果做比较,只为得到最优的结果,最少的扔鸡蛋次数!result=Math.min(condition, result);}//当前子问题(当我有egg个鸡蛋,一共有floor层时)已经for循环完了!撒花~~接下来,就是把结果存到我们的结果矩阵里了!dp[egg][floor]=result;}}//以上的步骤在不断的往状态矩阵(我把它称作装满结果的大盘子!)填充结果!到这里已经都填充完毕,我们自然就可以取到我们想要的结果啦return dp[eggs][floors];}//(2)公式法   递推公式法public static int  dropEggs2(int eggs,int floors) {int times = 1;  while(DroppingMax(eggs, times) < floors)  {  ++times;  }  return times; }public static int DroppingMax( int eggs, int  times)  {  if(eggs == 1)  {  return times;  }  if(eggs >= times)  {  return (int)Math.pow(2, times) - 1;  }  return DroppingMax(eggs, times -1) + DroppingMax(eggs -1, times - 1) + 1;  }  public static void main(String[] args) {Scanner sin =new Scanner(System.in);while(sin.hasNext()) {String[]temp=sin.nextLine().split("\\s+");int eggs=Integer.parseInt(temp[0]);int floors=Integer.parseInt(temp[1]);// System.out.println(dropEggs(eggs,floors));System.out.println(dropEggs2(eggs,floors));}}
}

这里写图片描述

这篇关于扔鸡蛋问题-经典动态规划问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082357

相关文章

mybatis和mybatis-plus设置值为null不起作用问题及解决

《mybatis和mybatis-plus设置值为null不起作用问题及解决》Mybatis-Plus的FieldStrategy主要用于控制新增、更新和查询时对空值的处理策略,通过配置不同的策略类型... 目录MyBATis-plusFieldStrategy作用FieldStrategy类型每种策略的作

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

Python Jupyter Notebook导包报错问题及解决

《PythonJupyterNotebook导包报错问题及解决》在conda环境中安装包后,JupyterNotebook导入时出现ImportError,可能是由于包版本不对应或版本太高,解决方... 目录问题解决方法重新安装Jupyter NoteBook 更改Kernel总结问题在conda上安装了

pip install jupyterlab失败的原因问题及探索

《pipinstalljupyterlab失败的原因问题及探索》在学习Yolo模型时,尝试安装JupyterLab但遇到错误,错误提示缺少Rust和Cargo编译环境,因为pywinpty包需要它... 目录背景问题解决方案总结背景最近在学习Yolo模型,然后其中要下载jupyter(有点LSVmu像一个

解决jupyterLab打开后出现Config option `template_path`not recognized by `ExporterCollapsibleHeadings`问题

《解决jupyterLab打开后出现Configoption`template_path`notrecognizedby`ExporterCollapsibleHeadings`问题》在Ju... 目录jupyterLab打开后出现“templandroidate_path”相关问题这是 tensorflo

如何解决Pycharm编辑内容时有光标的问题

《如何解决Pycharm编辑内容时有光标的问题》文章介绍了如何在PyCharm中配置VimEmulator插件,包括检查插件是否已安装、下载插件以及安装IdeaVim插件的步骤... 目录Pycharm编辑内容时有光标1.如果Vim Emulator前面有对勾2.www.chinasem.cn如果tools工

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明