动态规划算法的优化技巧(转贴)

[摘要]
动态规划是信息学竞赛中一种常用的程序设计方法,本文着重讨论了运用动态规划思想解题时时间效率的优化。全文分为四个部分,首先讨论了动态规划时间效率优化的可行性和必要性,接着给出了动态规划时间复杂度的决定因素,然后分别阐述了对各个决定因素的优化方法,最后总结全文。

[正文]
一、引言
动态规划是一种重要的程序设计方法,在信息学竞赛中具有广泛的应用。
使用动态规划方法解题,对于不少问题具有空间耗费大、时间效率高的特点,因此人们在研究动态规划解题时更多的注意空间复杂度的优化,运用各种技巧将空间需求控制在软硬件可以承受的范围之内。但是,也有一部分问题在使用动态规划思想解题时,时间效率并不能满足要求,而且算法仍然存在优化的余地,这时,就需要考虑时间效率的优化。
本文讨论的是在确定使用动态规划思想解题的情况下,对原有的动态规划解法的优化,以求降低算法的时间复杂度,使其能够适用于更大的规模。

二、动态规划时间复杂度的分析
使用动态规划方法解题,对于不少问题之所以具有较高的时间效率,关键在于它减少了“冗余”。所谓“冗余”,就是指不必要的计算或重复计算部分,算法的冗余程度是决定算法效率的关键。动态规划在将问题规模不断缩小的同时,记录已经求解过的子问题的解,充分利用求解结果,避免了反复求解同一子问题的现象,从而减少了冗余。
但是,动态规划求解问题时,仍然存在冗余。它主要包括:求解无用的子问题,对结果无意义的引用等等。
下面给出动态规划时间复杂度的决定因素:
时间复杂度=状态总数*每个状态转移的状态数*每次状态转移的时间[1]
下文就将分别讨论对这三个因素的优化。这里需要指出的是:这三者之间不是相互独立的,而是相互联系,矛盾而统一的。有时,实现了某个因素的优化,另外两个因素也随之得到了优化;有时,实现某个因素的优化却要以增大另一因素为代价。因此,这就要求我们在优化时,坚持“全局观”,实现三者的平衡。

三、动态规划时间效率的优化

3.1 减少状态总数

我们知道,动态规划的求解过程实际上就是计算所有状态值的过程,因此状态的规模直接影响到算法的时间效率。所以,减少状态总数是动态规划优化的重要部分,本节将讨论减少状态总数的一些方法。

1、改进状态表示

状态的规模与状态表示的方法密切相关,通过改进状态表示减小状态总数是应用较为普遍的一种方法。
例一、 Raucous Rockers 演唱组(USACO`96)
[问题描述]
现有n首由Raucous Rockers 演唱组录制的珍贵的歌曲,计划从中选择一些歌曲来发行m张唱片,每张唱片至多包含t分钟的音乐,唱片中的歌曲不能重叠。按下面的标准进行选择:
(1) 这组唱片中的歌曲必须按照它们创作的顺序排序;
(2) 包含歌曲的总数尽可能多。
输入n,m,t,和n首歌曲的长度,它们按照创作顺序排序,没有一首歌超出一张唱片的长度,而且不可能将所有歌曲的放在唱片中。输出所能包含的最多的歌曲数目。
(1≤n, m, t≤20)
[算法分析]
本题要求唱片中的歌曲必须按照它们创作顺序排序,这就满足了动态规划的无后效性要求,启发我们采用动态规划进行解题。
分析可知,该问题具有最优子结构性质,即:设最优录制方案中第i首歌录制的位置是从第j张唱片的第k分钟开始的,那么前j-1张唱片和第j张唱片的前k-1分钟是前1..i-1首歌的最优录制方案,也就是说,问题的最优解包含了子问题的最优解。
设n首歌曲按照写作顺序排序后的长度为long[1..n],则动态规划的状态表示描述为:
g[i, j, k],0≤i≤n,0≤j≤m,0≤k<t,表示前i首歌曲,用j张唱片另加k分钟来录制,最多可以录制的歌曲数目,则问题的最优解为g[n,m,0]。由于歌曲i有发行和不发行两种情况,而且还要分另加的k分钟是否能录制歌曲i。这样我们可以得到如下的状态转移方程和边界条件:
当k≥long[i],i≥1时:
g[i, j, k]=max{g[i-1,j,k-long[i]],g[i-1,j,k]}
当k<long[i],i≥1时:
g[i, j, k]=max{g[i-1,j-1,t-long[i]],g[i-1,j,k]}
规划的边界条件为:
当0≤k<t时:g[0,0,k]=0;
我们来分析上述算法的时间复杂度,上述算法的状态总数为O(n*m*t),每个状态转移的状态数为O(1),每次状态转移的时间为O(1),所以总的时间复杂度为O(n*m*t)。由于n,m,t均不超过20,所以可以满足要求。
[算法优化]
当数据规模较大时,上述算法就无法满足要求,我们来考虑通过改进状态表示提高算法的时间效率。
本题的最优目标是用给定长度的若干张唱片录制尽可能多的歌曲,这实际上等价于在录制给定数量的歌曲时尽可能少地使用唱片。所谓“尽可能少地使用唱片”,就是指使用的完整的唱片数尽可能少,或是在使用的完整的唱片数相同的情况下,另加的分钟数尽可能少。分析可知,在这样的最优目标之下,该问题同样具有最优子结构性质,即:设D在前i首歌中选取j首歌录制的最少唱片使用方案,那么若其中选取了第i首歌,则D-{i}是在前i-1首歌中选取j-1首歌录制的最少唱片使用方案,否则D前i-1首歌中选取j首歌录制的最少唱片使用方案,同样,问题的最优解包含了子问题的最优解。
改进的状态表示描述为:
g[i, j]=(a, b),0≤i≤n,0≤j≤i,0≤a≤m,0≤b≤t,表示在前i首歌曲中选取j首录制所需的最少唱片为:a张唱片另加b分钟。由于第i首歌分为发行和不发行两种情况,这样我们可以得到如下的状态转移方程和边界条件:
g[i, j]=min{g[i-1,j],g[i-1,j-1]+long[i]} 
其中(a, b)+long[i]=(a’, b’)的计算方法为:
当long[i]≤t-b时: a’=a;     b’=b+long[i];
当long[i]>t-b时: a’=a+1;   b’=long[i];
规划的边界条件:
g[i,0]=(0,0)  0≤i≤n
这样题目所求的最大值是:ans=max{k| g[n, k]≤(m-1,t)}
改进后的算法,状态总数为O(n2),每个状态转移的状态数为O(1),每次状态转移的时间为O(1),所以总的时间复杂度为O(n2)。值得注意的是,算法的空间复杂度也由改进前的O(m*n*t)降至优化后的O(n2)。
(程序及优化前后的运行结果比较见附件)
通过对本题的优化,我们认识到:应用不同的状态表示方法设计出的动态规划算法的性能也迥然不同。改进状态表示可以减少状态总数,进而降低算法的时间复杂度。在降低算法的时间复杂度的同时,也降低了算法的空间复杂度。因此,减少状态总数在动态规划的优化中占有重要的地位。

2、选择适当的规划方向

    动态规划方法的实现中,规划方向的选择主要有两种:顺推和逆推。在有些情况下,选取不同的规划方向,程序的时间效率也有所不同。一般地,若初始状态确定,目标状态不确定,则应考虑采用顺推,反之,若目标状态确定,而初始状态不确定,就应该考虑采用逆推。那么,若是初始状态和目标状态都已确定,一般情况下顺推和逆推都可以选用,但是,能否考虑选用双向规划呢?
双向搜索的方法已为大家所熟知,它的主要思想是:在状态空间十分庞大,而初始状态和目标状态又都已确定的情况下,由于扩展的状态量是指数级增长的,于是为了减少状态的规模,分别从初始状态和目标状态两个方向进行扩展,并在两者的交汇处得到问题的解。
上述优化思想能否也应用到动态规划之中呢?来看下面这个例子。
例二、 Divide (Merc`2000)
[问题描述]
有价值分别为1..6的大理石各a[1..6]块,现要将它们分成两部分,使得两部分价值和相等,问是否可以实现。其中大理石的总数不超过20000。(英文试题详见附件)
[算法分析]
令S=∑(i*a[i]),若S为奇数,则不可能实现,否则令Mid=S/2,则问题转化为能否从给定的大理石中选取部分大理石,使其价值和为Mid。
这实际上是母函数问题,用动态规划求解也是等价的。
m[i, j],0≤i≤6,0≤j≤Mid,表示能否从价值为1..i的大理石中选出部分大理石,使其价值和为j,若能,则用true表示
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值