算法设计与分析 实验4 动态规划法求扔鸡蛋问题

目录

一、实验目的

二、问题描述

三、实验要求

四、实验内容

动态规划法

算法描述

算法伪代码描述

算法复杂度分析

数据测试

二分优化的动态规划法

算法描述

二分优化:

算法伪代码

算法复杂度分析

数据测试

单调决策优化的动态规划法

算法描述

算法伪代码描述

算法复杂度分析

数据测试

空间降维优化

算法分析

算法伪代码描述

数据测试

综合分析

五、实验结论


一、实验目的

        1. 掌握动态规划算法设计思想。

        2. 掌握扔鸡蛋问题的动态规划法。

二、问题描述

        扔鸡蛋问题是计算机程序设计中的一个经典问题。从一幢楼房的不同楼层往下扔鸡蛋,用最少的最坏情况试验次数,确定鸡蛋不会摔碎的最高安全楼层。仅有一个鸡蛋供试验时,只能采用顺序查找法。有足够多的鸡蛋时,可以采用二分查找法。有多于一个但数量有限的鸡蛋时,采用动态规划方法求解。双蛋问题(two-egg problem)是本问题的一个特例,曾出现于谷歌的程序员面试题中。

        有一幢楼房高层。某人准备了N个鸡蛋供试验。他想知道鸡蛋从几层扔下不会摔碎,并确定出最高安全楼层。试验过程中,鸡蛋没有摔碎则可以继续使用,摔碎了则需要换一个鸡蛋继续试验。为保证试验成功,此人要设计一个程序,以最小化最坏情况的试验次数F(M, N)。作为一个数学抽象,本问题采用一些理想化假设:所有鸡蛋抗摔能力相同,不计重复坠地的累积损伤,且忽略试验结果的偶然性。试验成功的标准是在N个鸡蛋用完之前,精确确定最高安全楼层是哪一层。允许有鸡蛋剩余。

        如果只有N=1个鸡蛋供试验,则为了保证试验成功,只能从一层开始逐层往上试验。这相当于采用顺序查找算法,最坏试验次数F(M, 1)=M。如果一层就碎了,则最高安全楼层为0。如果M层还不碎,则最高安全楼层为M。

三、实验要求

        1. 给出解决问题的动态规划方程;

        2. 理论分析该算法的时间复杂度;

        3. 分别测试M=10000, 20000, …, 100000, N=20时以及M=50000, N=11, 12, …, 20时的算法运行时间,并分析实验结果;

        4. 依次在终端输出M=10000, N=1~20时的F(M, N)值,实验课时检查该代码,限用C或C++语言编写。

四、实验内容

动态规划法
算法描述

        动态规划的优势在于对于每一个子问题都只求解一次,而后将该结果保存,但再次对

子问题的求解时直接使用即可,这样子避免了许多子问题被重复计算多次,造成的时间复杂度较高,耗时较长的问题。

       因此,我对状态进行了如下定义:

              dpi,j 表示用i个鸡蛋可以确认j层楼的门槛层的最少操作次数

       在状态定义完成后,便要考虑动态规划的另一个条件,初始态,即边界条件,从题目描述中我们可以得知,当鸡蛋数i=1时,对于j层楼我们需要从第一层楼开始向上测试,所需要的最少操作数目为dp1,j =j,当楼层数j=0时,对于i个鸡蛋,我们需要的最少操作次数为dpi,0 =0。

       对于每一个状态,对其考虑状态转移

       对于i个鸡蛋𝑗层楼,在第𝑥层(1 ≤ 𝑥 ≤ 𝑗)扔鸡蛋时,我们用𝑝𝑥表示确定门槛层需要的操作次数。对于每个鸡蛋:

        • 若鸡蛋破碎,子问题的规模是鸡蛋数变为i - 1,楼层数变为𝑥 - 1层,其最优解为dpi-1,x-1 ,最后再加上本次的操作次数,所以操作次数 𝑝𝑥 =dpi-1,x-1  + 1;

        • 若鸡蛋没有破碎,此时子问题的规模是鸡蛋数不变,楼层数变为𝑗 - 𝑥层,其最优解为𝑑𝑝𝑖,𝑗-𝑥,最后再加上本次的操作次数,所以操作次数 𝑝𝑥 = dpi,j-x  + 1。

       但由于我们并不知道扔下去的鸡蛋是否会碎,因此我们要在两种情况的查找次数中选择最大值,即考虑最坏的情况,所以𝑝𝑥 = max(dpi-1,x-1 , dpi,j-x ) + 1

        综上分析,可以写出动态规划方程:

dpi,j = { p1 , p2 ,p3 ,……., pj }

       即                                      dpi,j=min⁡{max(dpi-1,x-1, dpi,j-x) + 1}  1<=x<=j

                                                 其中,边界条件为dp1,j =j,dpi,0 =0

       动态规划的过程实际上就是一个填表的过程,以下为模拟填表的过程:当我们要填𝑑𝑝4,6的时候,根据动态规划方程,我们需要枚举每一个扔鸡蛋的楼层𝑥(1 ≤ 𝑥 ≤ 6)作为我们的上一个状态,所有的状态中选择最小的答案即为我们的答案。

算法伪代码描述

算法复杂度分析

        对于n个鸡蛋和m层楼的跌落实验:

                时间复杂度:状态数量一共为n*m个,并且对于每个状态枚举扔鸡蛋的楼层需要O(m)的时间,一共为O(nm2)

                空间复杂度:由于所有的状态需要 O(1)的空间存储,所以空间复杂度为𝑂(nm)

数据测试

        为降低偶然性,我们对每组数据重复测试 10 次再取平均值,并利用公式T=T0*n*m2n0*m0^2 绘制理论运行时间曲线。

当M=10000, 20000, …, 100000, N=20时

楼层 m

10000

20000

30000

40000

50000

60000

70000

80000

90000

100000

操作数

14

15

15

16

16

16

17

17

17

17

实际耗时s

13.5

54.3

122.6

210.9

329.2

472.3

642.5

839.4

1072.1

1320.7

理论耗时s

13.5

54.0

121.5

216.0

337.5

486.0

662.5

864.0

1093.5

1350

        由上图所示,蓝色曲线为动态规划法实际运行时间拟合曲线,橙色曲线为动态规划法理论运行时间拟合曲线,两条曲线基本吻合,故动态规划法的时间复杂度满足𝑂(nm2)。

        当M=50000, N=11, 12, …, 20,程序无法在可接受的时间内求出答案

       由于最基本的动态规划方程,其时间复杂度仍达到了n^3级,在面对大规模数据时,需要较长的时间才能计算出来,因此算法优化就十分重要

二分优化的动态规划法
算法描述

        对于动态规划方程:

dpi,j=min⁡{max(dpi-1,x-1, dpi,j-x) + 1}   1<=x<=j

       我们可以清晰的看到,dpi,j 是一个关于楼层j的单调递增函数,但鸡蛋数i固定下来时,楼层j越高,所需要的操作数也会变多,因此,在上述转移方程中,dpi-1,x-1 项是一个随x增加而单调递增的函数,而dpi,j-x 是一个随x的增加而单调递减的函数,而我们需要求得的是,找到一个位置它的最大值是所有位置中最小的

        从上图中我们可以轻松找到那个位置,即为两个函数dpi-1,x-1, dpi,j-x 变化曲线相交的点x0即可,x0可保证两个函数的最大值最小。

        但由于dpi-1,x-1dpi,j-x 都是离散函数,我们两个函数的交点可能不是整数。所以我们选择去找离这两个函数交点左右两侧最近的整数,然后取二者更优的解作为x0。 也就是说, 我们需要找到最大的满足 dpi-1,x-1  ≤ dpi,j-x  的𝑥1,以及最小的满足 dpi-1,x-1  ≥ dpi,j-x 的𝑥2,其中能保证𝑥1 + 1 = 𝑥2。

二分优化:

        我们在所有满足条件的 𝑥 上进行二分查找。对于状态𝑑𝑝𝑖,𝑗而言, 𝑥 范围是 [1,𝑗]中的任一整数。 在二分查找的过程中,假设当前这一步我们查找到了𝑥𝑚𝑖𝑑,如果 𝑑𝑝𝑖-1,𝑥𝑚𝑖𝑑-1 ≥ 𝑑𝑝𝑖,𝑗-𝑥𝑚𝑖𝑑,那么真正的𝑥𝑜𝑝𝑡一定在 𝑥𝑚𝑖𝑑 的左侧,否则真正的𝑥𝑜𝑝𝑡在 𝑥𝑚𝑖𝑑的右侧。

算法伪代码

算法复杂度分析

        对于n个鸡蛋和m层楼的跌落实验:

                时间复杂度:状态数量一共为n*m个,由于使用的是二分查找,每个状态找特定位置x0需要O(lgm)的时间,所有时间复杂度一共为O(nmlgm)

                空间复杂度:由于所有的状态需要 O(1)的空间存储,所以空间复杂度为𝑂(nm)

数据测试

        为降低偶然性,我们对每组数据重复测试 10 次再取平均值,并利用公式T=T0*n*m*lgmn0*m0*lgm0 绘制理论运行时间曲线。

        当M=10000, 20000, …, 100000, N=20时

楼层 m

10000

20000

30000

40000

50000

60000

70000

80000

90000

100000

操作数

14

15

15

16

16

16

17

17

17

17

实际耗时ms

59.6

127.7

194.2

269.4

332.4

417.9

478.4

557.4

620.9

700.4

理论耗时ms

59.6

128.1

200.1

274.2

350.0

427.1

505.3

584.4

664.3

745.0

        当M=50000, N=11, 12, …, 20时

鸡蛋数 n

11

12

13

14

15

16

17

18

19

20

操作数

14

14

14

14

14

14

14

14

14

14

实际耗时ms

178.6

193.3

208.7

223.4

240.9

265.1

273.5

296.0

324.5

337.4

理论耗时ms

178.6

194.3

211.0

227.3

243.5

259.7

276.0

292.5

308.4

324.7

        两条曲线基本吻合,故二分优化的动态规划算法的时间复杂度满足𝑂(nm log m),曲线上升趋势也符合复杂度的分析

单调决策优化的动态规划法
算法描述

        对于动态规划方程:

dpi,j=min⁡{max(dpi-1,x-1, dpi,j-x) + 1}   1<=x<=j

        如果我们固定鸡蛋数ⅈ, 随着楼层数𝑗的增加, 状态转移方程中dpi,j-x 这一项的值也会增加, 而对于状态转移方程中dpi-1,x-1 这一项,它的值是不变的,因为它和 𝑗无关。在二分优化的过程中,我们知道dpi-1,x-1 随着𝑥单调递增,而dpi,j-x 随着𝑥单调递减,那么当𝑗增加时, dpi,j-x 对应的函数折线图在每个整数点上都是增加的, 如下图所示。 因此在dpi-1,x-1 不变的情况下, 随着𝑗增加, x0是单调递增的

       与实验2中求中间区域的最短路径相同,对于楼层j,我们寻找特定位置x0是并不需要对1~j进行二分查找,而是在之前x0的基础上进行递增查找,如此一一对应的查找,均摊下来的时间复杂度为O(1)

算法伪代码描述

算法复杂度分析

        对于n个鸡蛋和m层楼的跌落实验:

                时间复杂度: 状态变量依然是n*m个, 每个状态找扔鸡蛋的楼层𝑥𝑜𝑝𝑡均摊下来的转移时间复杂度是𝑂(1), 所以时间复杂度一共为𝑂(nm)。

                空间复杂度:由于所有的状态需要 O(1)的空间存储,所以空间复杂度为𝑂(nm)

数据测试

        为降低偶然性,我们对每组数据重复测试 10 次再取平均值,并利用公式T=T0*n*mn0*m0 绘制理论运行时间曲线。

        当M=10000, 20000, …, 100000, N=20时

楼层 m

10000

20000

30000

40000

50000

60000

70000

80000

90000

100000

操作数

14

15

15

16

16

16

17

17

17

17

实际耗时ms

3.9

10.1

12.4

16.9

24.4

28.5

29.5

31.1

36.9

40.6

理论耗时ms

3.9

7.8

11.7

15.6

19.5

23.4

27.3

31.2

35.1

39.0

        当M=50000, N=11, 12, …, 20时

鸡蛋数 n

11

12

13

14

15

16

17

18

19

20

操作数

14

14

14

14

14

14

14

14

14

14

实际耗时ms

10.1

13.9

12.2

13.7

16.0

15.2

16.1

19.2

18.9

19.2

理论耗时ms

10.1

11.0

11.9

12.8

13.7

14.6

15.6

16.5

17.4

18.3

        蓝色曲线为决策单调性优化的动态规划算法实际运行时间拟合曲线,橙色曲线为决策单调性优化的动态规划算法理论运行时间拟合曲线,实际时间在理论时间上下波动,两条曲线基本吻合,故决策单调性优化的动态规划算法的时间复杂度满足𝑂(nm)。

空间降维优化
算法分析

         对单调决策优化的动态规划法观察可以发现,状态在转移时只涉及第i−1层与第i层,第i−1层以前的状态已经不需要了,我们考虑不保存之前的状态以节省空间。为此,我们可以用两个一维数组分别表示第i−1层与第i层,从而代替整个二维数组。这样转换对于时间复杂度是没有影响的,而空间复杂度便为了O(n)。

算法伪代码描述

数据测试

        为降低偶然性,我们对每组数据重复测试 10 次再取平均值,并利用公式T=T0*n*mn0*m0 绘制理论运行时间曲线。

        当M=10000, 20000, …, 100000, N=20时

楼层 m

10000

20000

30000

40000

50000

60000

70000

80000

90000

100000

操作数

14

15

15

16

16

16

17

17

17

17

实际耗时ms

1.84

3.25

2.01

6.96

7.68

5.89

7.19

7.46

8.38

12.34

理论耗时ms

1.84

3.68

5.52

7.36

9.2

11.04

12.88

14.72

16.56

18.4

         当M=50000, N=11, 12, …, 20时

鸡蛋数 n

11

12

13

14

15

16

17

18

19

20

操作数

14

14

14

14

14

14

14

14

14

14

实际耗时ms

5.0

5.4

6.4

7.4

9.3

7.5

9.2

9.6

10.3

10.9

理论耗时ms

5.0

5.4

5.9

6.4

6.8

7.2

7.7

8.3

8.6

9.2

       将其消耗的时间与(三)中未进行空间优化的算法消耗时间进行比较,可以明显的看出,通过空间优化,程序运行的效率得到了一个较大的提升。

综合分析

        将动态规划法,通过二分优化、单调决策优化、以及降维单调决策优化的测试结果进行对比分析可以看到:

        当M=10000, 20000, …, 100000, N=20时

        当M=50000, N=11, 12, …, 20时

        从上述两个图表的消耗时间对比我们可以看出:

决策+空间dp << 二分 dp < 朴素 dp

        对于朴素动态规划算法,通过填表形式保存已求解过的状态,明显提高了算法效率,在小规模数据上速度较快,但面对大规模数据,其复杂度依旧很高,并不适用

        其次是二分优化 dp, 由于其在状态转移的时候使用的是二分查找, 所以对所选楼层的查找是𝑂(log𝑛)的复杂度, 因此对于原本需要𝑂(n)时间复杂度来查找的朴素 dp, 在算法效率上由有所提高。

        决策单调性优化 dp 利用了状态转移过程中x0的单调性, 在找当前状态的x0时不断利用前一个x0来查找, 利用了这种单调性, 使其查找的时间复杂度均摊下来是𝑂(1), 因此算法效率上对于二分查找优化 dp 又有进一步的提升

        最后是在空间上的优化,将不再需要的空间释放掉,防止内存被消耗完,并可以减少程序在搜索上消耗的时间

五、实验结论

        在本次实验中,我使用了动态规划算法对鸡蛋掉落问题进行了求解

        动态规划算法利用了子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后该子问题的求解时直接查表, 这种用空间换时间的方法使时间复杂度降低为了𝑂(𝑘𝑛2), 但结果还是不够优秀。 之后我们还提出了 3 种优化算法, 分别为: 二分优化、 决策单调性优化和降维优化。 最后对各个算法进行多次测试与比较, 在算法的运行时间上我们得出以下结果:

单调决策+降维优化 dp< 单调决策优化 dp < 二分优化 dp < 朴素 dp

        使用单调决策加降维优化的动态规划算法在终端输出M=10000, N=1~20时的F(M, N)值为:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/727673.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Ardiuno】实验使用ESP32接收电脑发送的串口数据(图文)

使用ESP32可以非常方便的与电脑进行串口通讯&#xff0c;一般我们可以用串口接收ESP32的输出作为调试使用&#xff0c;今天我们再来实验一下从电脑端向ESP32单片机发送数据。 发送数据程序代码&#xff1a; void setup() {Serial.begin(9600); }void loop() { if(Serial.ava…

股票核心因子解读以及如何从接口获取股票数据信息

目录 1 股票基础信息1.1 股票核心因子1.2 获取股票信息 2 如何从接口获取股票数据2.1 yfinance2.2 finnhub-python2.3 alpha_vantage2.4 efinance2.4 Tushare 3 如何从各大金融平台获取咨询信息3.1 国外3.2 国内 1 股票基础信息 1.1 股票核心因子 基本面因子 因子名称计算公…

前缀和+双指针,CF 131F - Present to Mom

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 131F - Present to Mom 二、解题报告 1、思路分析 很经典的一种把列看作cell 来进行双指针/递推的题型 我们考虑&#xff0c;可以预处理出原矩阵中的所有star 然后我们去枚举矩形的上下边界&#xff0c;把…

java读取wps嵌入式图片思路

这个只写了思路具体代码在文章最后&#xff0c;不想了解得直接去拿代码 了解Excel数据结构 Excel 文件格式后缀xls,xlsx 其实是一个压缩文件&#xff0c;是由多个文件夹以及xml 文件组合为一个文件&#xff0c;xml文件记录了Excel得内容以及样式等信息。加入在桌面新建一个xls…

MySQL之复制(七)

复制 定制的复制方案 分离功能 许多应用都混合了在线事务处理(OLTP)和在线数据分析(OLAP)的查询。OLTP查询比较短并且是事务型的。OLAP查询则通常很大&#xff0c;也很慢&#xff0c;并且不要求绝对最新的数据。这两种查询给服务器带来的负担完全不同&#xff0c;因此它们需…

一文教你在centos 7.9中安装mysql5.7(超级详细)

##red## &#x1f534; 大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff0c;雄雄的小课堂。 一、前言 每当新来一个服务器之后&#xff0c;习惯性的都会安装一个宝塔面板&#xff0c;不为别的&#xff0c;就为了装环境方便点儿&#xff0c;比如常用的jdk,m…

python的赋值运算

# coding:utf-8 x20 #直接复制&#xff0c;直接将20赋值给x y10 xxy #将xy的和赋值给给x print(x) xy print(x)#40 x-y #相当于x-y print(x) #30x*y #xx*y x/y #xx/y print(x) x%2#xx%2 print(x)#0.0 隐式转换 z3 y//z #yy//z y**2#yy**2 #python支持链式赋值 abc100#相当于a10…

【ai】tx2-nx 查看 jetpack 版本信息及对应的tritonserver

3 jtop nvidia@tx2-nx:~$ jtop [WARN] Board missing UNKNOWN (press CTRL + Click) nvidia@tx2-nx:~$ 点击info 可以看到 jetpack是4.6opencv 是4.1.15.1.2 的不适合我 tritonserver2.35.0-jetpack5.1.2-update-2.tgz tritonserver2.19.0-jetpack4.6.1.tgz. 4.6.1<

【已解决】better-scroll在PC端如何开启鼠标滚动以及如何始终显示滚动条

总结 需要安装插件 mouse-wheel 和 scrollbar 在PC端如何开启鼠标滚动? 需要安装官方提供的滚动插件&#xff1a;mouse-wheel https://better-scroll.github.io/docs/zh-CN/plugins/mouse-wheel.html 为了开启鼠标滚动功能&#xff0c;你需要首先引入 mouseWheel 插件&…

华为设备SSH远程访问配置实验简述

一、实验需求: 1、AR1模拟电脑SSH 访问AR2路由器。 二、实验步骤&#xff1a; 1、AR1和AR2接口配置IP&#xff0c;实现链路通信。 2、AR2配置AAA模式 配置用户及密码 配置用户访问级别 配置用户SSH 访问服务 AR2配置远程服务数量 配置用户远程访问模式为AAA 配置允许登录接入用…

Mysql 8.3.0 安装

Mysql 8.3.0 安装地址&#xff1a;MySQL :: Download MySQL Community Server (Archived Versions) 下载链接&#xff1a;https://downloads.mysql.com/archives/get/p/23/file/mysql-8.3.0-linux-glibc2.28-x86_64.tar.xz 解压&#xff1a; tar -xvf mysql-8.3.0-linux-glib…

RS-232协议详解:深入理解与实际应用

RS-232协议详解 RS-232协议&#xff0c;也称为推荐标准232&#xff0c;是一种用于串行通信的标准协议。它在计算机和外围设备之间的通信中广泛应用。本文将详细介绍RS-232协议的各个方面&#xff0c;包括其历史、工作原理、信号类型、连接方式、应用场景等。希望通过这篇文章&a…

代码大模型揭秘:从下载到推理,全流程体验StarCoder

选择模型 模型榜单 大模型的发展日新月异&#xff0c;性能强劲的大模型不断涌现&#xff0c;可以实时关注开源大模型的榜单&#xff0c;选择合适自己的大模型 开源大模型榜单 开源代码大模型榜单 模型网站 目前主流的下载模型的网站就是 huggingface 全球社区&#xff0c;…

(四十三)Vue Router之嵌套路由

文章目录 什么是嵌套路由嵌套路由的使用demo 上一篇&#xff1a;&#xff08;四十二&#xff09;Vue之路由及其基本使用Vue Router 什么是嵌套路由 实际生活中的应用界面&#xff0c;有可能由多层嵌套的组件组合而成。同样地&#xff0c;URL 中各段动态路径也按某种结构对应嵌…

JEnv-for-Windows 详细使用

管理员执行jenv.bat文件 执行正常, 接下来就是按照官网的命令就行了 文件下载地址 https://download.csdn.net/download/qq_43071699/89462664 JEnv 是一个强大的Java版本管理工具&#xff0c;允许开发者在多个Java版本之间轻松切换。以下是一些常用的JEnv命令&#xff0c;这…

JVM常用概念之扁平化堆容器

扁平化堆容器是OpenJDK Valhalla 项目提出的&#xff0c;其主要目标为将值对象扁平化到其堆容器中&#xff0c;同时支持这些容器的所有指定行为&#xff0c;从而达到不影响原有功能的情况下&#xff0c;显著减少内存空间的占用&#xff08;理想条件下可以减少24倍&#xff09;。…

成为AIGC人才,是职场人当下的必修课?

随着科技的飞速进步&#xff0c;人工智能和机器学习技术正逐渐渗透到我们生活的每一个角落&#xff0c;其中&#xff0c;人工智能生成内容&#xff08;AIGC&#xff09;更是以其独特的魅力和广泛的应用前景&#xff0c;成为当下科技领域的热门话题。在这样的背景下&#xff0c;…

Kubernetes容器运行时:Containerd vs Docke

容器化技术笔记 Kubernetes容器运行时&#xff1a;Containerd vs Docke - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this arti…

Postman Postman接口测试工具使用简介

Postman这个接口测试工具的使用做个简单的介绍&#xff0c;仅供参考。 插件安装 1&#xff09;下载并安装chrome浏览器 2&#xff09;如下 软件使用说明

鸿蒙开发通信与连接:【@ohos.rpc (RPC通信)】

RPC通信 本模块提供进程间通信能力&#xff0c;包括设备内的进程间通信&#xff08;IPC&#xff09;和设备间的进程间通信&#xff08;RPC&#xff09;&#xff0c;前者基于Binder驱动&#xff0c;后者基于软总线驱动。 说明&#xff1a; 本模块首批接口从API version 7开始支…