《算法导论》学习分享——15. 动态规划

15. 动态规划

动态规划和分治法相似,都是通过组合子问题的解来求解原问题的解。但不同的是分治法将问题划分为不相交的子问题,递归的求解子问题,再将它们的解组合起来,求出原问题的解。相反,动态规划应用于子问题相互重叠的情况,即不同的子问题具有公共的子子问题。这种情况下,用分治法会反复的求解相同的子问题,造成时间浪费。动态规划对每个子问题只求解一次,并且保存在表格中,从而避免重复计算。

动态规划通常用于求解最优化问题。

我们通常按照如下步骤设计一个动态规划算法:

  1. 刻画一个最优解的结构特点
  2. 递归的定义最优解的值
  3. 计算最优解的值,通常采用自底而上的方法
  4. 利用计算出的信息构造一个最优解

如果只需要最优解的值,而非最优解本身,可忽略第四步。如果需要做第四步,往往需要在执行第三步时维护一些额外信息。

钢条切割

钢条切割问题:给定一段长度为n英寸的钢条和一个价格表pi(i=1,2…n),求切割方案使得收益rn最大。

15_1.PNG

考虑当n=4时,所有的切割方案如下,我们发现当把4英寸的钢条切割为两段2英寸长的钢条时产生的收益最大。

15_2.PNG

当区分1+3切法和3+1切法时,n英寸的钢条有2n-1种切割方案。
我们可以手动得到ri,及对应切割方案:

15_CUT_RESULT1.PNG

对于rn,我们可以用更短的钢条的最优切割收益来描述它:
rn=max(pn,r1+rn1,r2+rn2,...,rn1+r1). r n = m a x ( p n , r 1 + r n − 1 , r 2 + r n − 2 , . . . , r n − 1 + r 1 ) .

这时我们找到了钢条切割问题的最优子结构。每次切割后我们可以把切开的两段钢条看做独立的钢条切歌问题。一段钢条的最优解为所有切割方案中最大的。
我们可以将rn的式子简化为: rn=max1in(pi+ini) r n = max 1 ≤ i ≤ n ( p i + i n − i ) .

自顶而下的递归实现

根据上面的式子,我们可以得到下面这种自顶而下的递归实现(p为价格数组):
15_CUT_ROD.PNG

这种实现的递归式为: T(n)=1+j=0n1T(j). T ( n ) = 1 + ∑ j = 0 n − 1 T ( j ) .
我们可以求得 T(n)=2i T ( n ) = 2 i ,这个时间是非常惊人的,而这么大的原因就是因为包含了非常多的重复计算。下图是递归树,红线圈起来的都是重复计算部分。

/.res/15_3.PNG

使用动态规划方法
  • 带备忘的自顶而下法
    与前面的递归方法类似,但是用了一个数组r[1..n]记录最优解,如果发现r[n]已经有记录,则无需重复计算,直接返回该值。
    15_MEMORIZED_CUT_ROD.PNG
  • 自底而上法
    自底而上法采用子问题的自然顺序,依次求解规模为j=1,2…,n的子问题。
    15_BOTTOM_UP_CUT_ROD.PNG

无论是带备忘的自顶而下法还是自底而上法,其中都是用了一个额外数组来存储子问题的最优解,从而避免重复计算子问题的解。动态规划付出额外的内存空间来节省时间,是典型的时空权衡的例子。

子问题图

当思考动态规划问题时,弄清所涉及子问题及子问题之间的依赖关系很关键。
问题的子问题图准确的表达了这些信息:
15_4.PNG
途中结点表示钢条切割的子问题规模,箭头表示子问题之间的依赖关系。
有了子问题图,我们便可轻易的得知自底而上的顺序应该如何。
而且子问题图G=(V, E)还可以帮助我们确定动态规划算法的运行时间。由于每个子问题只求解一次,因此算法运行时间等于每个子问题求解时间之和。通常,一个子问题的求解时间与子问题图中对应顶点的度(射出边的数目)成正比,而子问题的数目等于子问题图的顶点数。因此,通常情况下,动态规划算法的运行时间与顶点和边数量呈线性关系。

重构解

前面的方法只给出的如何求出最优解的值,但并未返回解本身。
下面是基于自底而上动态规划算法的扩展,其中用数组s[0..n]存储n英寸钢条的最优切割方案,s[i]存储的数字表示,i英寸的钢条切割为s[i]英寸和i-s[i]英寸时最优,其中s[i]英寸部分不再切割,i-s[i]英寸部分的最优解需要递归查看。
所以可以通过PRINT-CUT-ROD-SOLUTION来打印出n英寸钢条的一个最优切割方案。
15_EXTEND_BOTTOM_UP_CUT_ROD.PNG

矩阵链乘法

给定一个n个矩阵的序列(矩阵链) <A1,A2,...,An> < A 1 , A 2 , . . . , A n > <script type="math/tex" id="MathJax-Element-5"> </script>,我们希望求他们的乘积 A1A2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值