算法设计与分析 实验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.mzph.cn/pingmian/31013.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多线程下JVM内存模型 和 volatile关键字

1、线程的概念 线程&#xff08;thread&#xff09;是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流&#xff0c;一个进程中可以并发多个线程&#xff0c;每条线程并行执行不同的任务…

微软修复Wi-Fi驱动高危漏洞 影响Windows所有版本 可通过局域网发起攻击

微软修复 WiFi 驱动程序中的高危安全漏洞&#xff0c;该漏洞影响 Windows 所有版本&#xff0c;可以通过公共 WiFi 等发起攻击。如果攻击者能够接入到目标设备所处的网络中&#xff0c;则可以悄无声息完成攻击&#xff0c;不需要用户进行任何交互。 在本月例行安全更新中微软修…

oracle 主从库中,从库APPLIED为YES ,但是主库任然为NO

主库 从库 从库已经APPLIED但是主库为APPLIED&#xff0c; 主数据库和备用数据库之间的ARCH-RFS心跳Ping负责更新主数据库上v$archived_log的APPLICED列。 在主数据库上有一个指定的心跳ARCn进程来执行此Ping。如果此进程开始挂起&#xff0c;它将不再与远程RFS进程通信&#…

WEB自动化测试(selenium工具)框架、面试题

一、什么是web自动化测试 让程序员代替人为去验证web项目功能的过程 二、什么web项目适合自动化测试 1)需求变动不频繁 测试脚本的稳定性决定了自动化测试的维护成本。如果软件需求变动过于频繁&#xff0c;测试人员需要根据变动的需求来更新测试用例以及相关的测试脚本&…

单木:面试官超爱问的字符串,今天给它彻底讲透

本文已收录于&#xff1a;https://github.com/danmuking/all-in-one&#xff08;持续更新&#xff09; 前言 哈喽&#xff0c;大家好&#xff0c;我是 DanMu。今天这边文章&#xff0c;想和大家聊聊有关字符串的问题&#xff0c;字符串似乎很简单&#xff0c;但其实字符串几乎…

MySQL之复制(七)

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

嵌入式linux系统中UART子系统基本实现

今天主要给大家分享一下,如何使用linux系统中的UART帧结构。 第一:UART串口波形 先观察UART波形,是如何被准确识别成字符D,而不是其他的内容呢? 当两个设备需要通过UART协议进行通讯时,它们需要同时约定好以下内容: 每—位信号的时间长度T(波特率= 1/T) 帧结构中每—…

fastadmin多语言切换设置

fastadmin版本&#xff1a;1.4.0.20230711 以简体&#xff0c;繁体&#xff0c;英文为例 一&#xff0c;在application\config.php 里开启多语言 // 是否开启多语言lang_switch_on > true, // 允许的语言列表allow_lang_list > [zh-cn, en,zh-tw], 二…

动态规划——达拉崩吧

1、题目链接 174. 地下城游戏 2、题目分析 假如说我们正向推状态转移方程&#xff0c;很难推出来&#xff0c;因为这道题有“加血”的说法&#xff0c;只能依靠后面的值判断前面所需要的血量&#xff0c;也就是说&#xff0c;如果正向的dp表示从起点出发&#xff0c;到达&…

【人工智能,机器学习,统计学习,科学表征】开源商用与研发合作

个体工户linjing-lab托管在Github&#xff0c;现公开招募商用与合作人员&#xff0c;目标人群分为以下几个方向&#xff1a; 数学、信息科学、计算机专业的大学高年级学生&#xff0c;熟悉C和面向对象模型&#xff0c;擅长Pybind11编译算子到Python环境。26岁以下的大学本科毕…

Srouce Insight 4出现乱码

今天用SI4打开一个工程文件&#xff0c;一打开发现注释全是乱码。中文全部看不出来&#xff0c;英文和数字可以看得出来。 那是因为中文的编码格式不算特别兼容。所以需要调整编码格式。 于是我在这里调整了编码格式&#xff1a; 找到菜单的Options-Preferences里面的Files 调…

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…

数据可视化实验五:seaborn绘制进阶图形

目录 一、绘制动态轨迹图 1.1 代码实现 1.2 绘制结果 二、使用seaborn绘制关系图 2.1 绘制散点图分析产品开发部已离职的员工的评分与平均工作时间 2.1.1 代码实现 2.1.2 绘制结果 ​编辑 2.2 基于波士顿房价数据&#xff0c;绘制房间数和房屋价格的折线图 2.2.1 代码…

vscode用vue框架写一个登陆页面

目录 一、创建登录页面 二、构建好登陆页面的路由 三、编写登录页代码 1.添加基础结构 2.给登录页添加背景 3.解决填充不满问题 4.我们把背景的红颜色替换成背景图&#xff1a; 5.在页面中央添加一个卡片来显示登录页面 6.设置中间卡片页面的左侧 7.设置右侧的样式及…

【深度学习】GELU激活函数是什么?

torch.nn.GELU 模块在 PyTorch 中实现了高斯误差线性单元&#xff08;GELU&#xff09;激活函数。GELU 被用于许多深度学习模型中&#xff0c;包括Transformer&#xff0c;因为它相比传统的 ReLU&#xff08;整流线性单元&#xff09;函数能够更好地近似神经元的真实激活行为。…

vue小总结

知识总结 【 1 】es6 语法总结 # let 定义变量 # const定义常量 ------块级作用域---- # var 以后尽量少用&#xff0c;函数作用域var 在 JavaScript 中是函数作用域或全局作用域。而 let 和 const 是块级作用域。 // 使用 var 声明全局变量 var globalVar "Im a globa…

【全网最全最详细】RabbitMQ面试题

一、说下RabbitMQ的架构大致是什么样的&#xff1f; RabbitMQ是一个开源的消息中间件&#xff0c;用于在应用程序之间传递消息。它实现了AMQP&#xff08;高级消息队列协议&#xff09;并支持其它消息传递协议&#xff0c;例如STOMP&#xff08;简单文本定向消息协议&#xff…

Linux环境编程基础学习2

For循环累加求和&#xff0c;两种方式&#xff0c;c方式的运算更快 打开文件操作 cat操作的实现 EOF: 1.diff A B比较两个文件是否一样&#xff0c;一样则什么结果都没有 Od -c 文件名可以显示出文件中的不可见字符

B站广告开户投流是什么政策?要哪些资质?

B站&#xff08;哔哩哔哩&#xff09;作为年轻人喜爱的视频分享社区&#xff0c;其广告价值也日益凸显。为了更好地服务广告主&#xff0c;B站近日对广告开户投流政策进行了更新&#xff0c;云衔科技作为专业的数字营销服务商&#xff0c;也积极响应&#xff0c;为广告主提供一…

绿茶集团重启IPO:流量渐退、业绩波动,还能讲出好故事吗?

近日&#xff0c;绿茶集团有限公司(下称“绿茶集团”)向港交所递交上市申请&#xff0c;花旗、招银国际为其联席保荐人。 回望绿茶集团的上市之路&#xff0c;可谓有诸多坎坷。该公司于2021年3月首度向港交所发起冲击&#xff0c;但却将中文版招股书中的“流动负债总额”错写成…