动态规划问题(一)——原理

一、问题描述
动态规划与分治方法相似,都是通过组合子问题的解来求解原问题。分治方法将问题划分为互不相交的子问题,递归地求解子问题,再将它们的解组合起来,求出原问题的解。与之相反,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题(子问题的求解是递归进行的,将其划分为更小的子子问题)。在这种情况下,分治算法会做许多不必要的工作,它会反复求解那些公共子子问题。而动态规划算法对每个子子问题只求解一次,将其解保存在一个表格中,从而无需每次求解一个子子问题时都重新计算,避免了这种不必要的计算工作。
动态规划方法通常用来求解最优化问题。这类问题可以有很多可行解,每个解都有一个值,我们希望寻找具有最优值(最小值或最大值)的解。我们称这样的解为问题的一个最优解,而不是最优解,因为可能有多个解都达到最优值。
通常按如下4个步骤来设计一个动态规划算法:
1.刻画一个最优解的结构特征
2.递归地定义最优解的值
3.计算最优解的值,通常采用自底向上的方法
4.利用计算出的信息构造一个最优解

二、动态规划原理
具备两个要素:最优子结构子问题重叠
(1)最优子结构:如果一个问题的最优解包含其子问题的最优解,就称此问题具有最优子结构性质。
最优子结构遵循如下的通用模式:
a.证明问题最优解的第一个组成部分是做出一个选择,例如,选择钢条第一次切割位置,选择矩阵链的划分位置 等。
b.对于一个给定问题,在其可能的第一步选择中,假定已经知道哪种选择才会得到最优解。
c.给定可获得最优解的选择后,确定这次选择会产生哪些子问题,以及如何最好地刻画子问题空间。
d.作为构成原问题最优解的组成部分,每个子问题的解就是它本身的最优解。
一个刻画子问题空间的好经验是:保持子问题空间尽可能简单,只在必要时才扩展它。
我们可以用子问题的总数和每个子问题需要考察多少种选择这两个因素的乘积来粗略分析动态规划算法的运行时间。对于钢条切割问题,共有Θ(n)个子问题,每个子问题最多需要考察n种选择,因此运行时间为O(n^2)。矩阵链乘法问题共有Θ(n^2)个子问题,每个子问题最多需要考察n-1种选择,因此运行时间为O(n^3).
注意:使用动态规划方法时要小心,要注意问题是否具有最优子结构性质。下面举两个栗子说明这个问题:
给定一个有向图:G=(V,E)和两个顶点u,v∈V.
①无权最短路径:找到一条从u到v的边数最少的简单路径。这条路径不包含环。
②无权最长路径:找到一条从u到v的边数最多的简单路径。同样不包含环。
可以证明,无权最短路径具有最优子结构性质,而无权最长路径不具有最优子结构性质。
①证明无权最短路径问题具有最优子结构性质:
反证法证明:
我们把路径u→v(p)分解为两条子路径u→w(p1)→v(p2),显然p的边数等于p1的边数加p2的边数。假定p是u 到v的最短路径,那么p1(p2)必须是u到w(w到v)的最短路径。
如果存在另一条从u到w的路径p1’ ,边数比p1少,那么可以剪掉p1而把p1’ 粘贴上,构造出一条比p边数更少的路径u→w(p1’)→v(p2’),与p为最优的假设矛盾。对称地可以证明p2必须是从w到v的最短路径。

②证明无权最长路径不具有最优子结构性质:
这里写图片描述
如图。路径q→r→t是q到t的一条最长简单路径,但q→r不是从q到r的一条最长简单路径(应该是q→s→t→r),同样地,r→t也不是从r到t的一条最长简单路径(应该是r→q→s→t)。如果我们组合最长简单径q→s→t→r和r→q→s→t,得到q→s→t→r→q→s→t,并不是简单路径。
思考:为什么最长简单路径问题的子结构与最短路径有这么大的区别?
原因在于:两个最长简单路径子问题时相关的,而两个最短路径子问题是无关的
子问题无关的含义是,同一个原问题的一个子问题不影响另一个子问题的解。对于本例,求q到t的最长简单路径 可以分解为两个子问题:求q到r的最长简单路径和r到t的最长简单路径。对于前者,我们选择路径q→s→t→r,其中用到了顶点s和t。由于两个子问题的解的组合必须产生一条简单路径,因此我们在求解第二个子问题的时候就不能再使用这两个顶点(s和t)了。但如果在求解第二个子问题时不允许使用顶点t,就根本无法继续求解,因为t是原问题的路径终点,是必须用到的。

(2)重叠子问题:如果递归算法反复求解相同的子问题,就称最优化问题具有重叠子问题性质。(与之相对的,适用分治方法求解得问题通常在递归地每一步都生成全新的子问题。)对每个子问题求解一次,将解存入一个表中,当再次需要这个子问题时直接查表。

发布了30 篇原创文章 · 获赞 97 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/HerosOfEarth/article/details/52202680