动态规划(dynamic programing)和分治法类似,都是通过组合子问题的解来求解原问题的解。(在经典排序算法中的二路归并排序和快速排序都用到了分而治之的思想-分治法)。
分治法是将原问题划分为没有交集,相互独立的子问题,并分别求解后再进行合并,求出原问题的解。
动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题。分治法会做许多不必要的工作,它会反复地求解那些公共子问题。动态规划算法对每个子问题只求解一次,将其解保存在一个表格中,从而无需每次求解一个子子问题时都需要重新计算。
动态规划上用来求解最优化问题(optimization problem)。
可以按照下面四个步骤来设计一个动态规划算法:
1、刻画一个最优解的结构特征。
2、递归地定义最优解的值。
3、计算最优解的值,通常采用自底向上的方法。
4、利用计算出的信息构造一个最优解。
最优子结构
用动态规划求解最优化问题的第一步就是刻画一个最优解的结构特征。如果一个问题的最优解包含其子问题的最优解,我们称此问题具有最优子结构性质。因此,某个问题是否适合用动态规划,它是否具有最优子结构性质是一个好的标准。使用动态规划方法时,我们用子问题的最优解来构造原问题的最优解。
如何发掘最优子结构的性质?
1、证明问题最优解的第一个组成部分是做出一个选择,而做出这个选择将会产生一个或多个待解的子问题。
2、对一个给定问题,在其可能的第一步选择中,假定已经知道哪种选择才会得到最优解。而我们并不关心这种选择具体是如何得到的,只是假定已经知道了这种选择。
3、给定获取的最优解选择后,确定这次选择会产生哪些子问题,以及如何最好地刻画子问题空间。
4、利用“剪切-粘贴(cut and paste)”技术证明作为构成原问题最优解组成部分,每个子问题的解就是它本身的最优解。
反证法:假定子问题的解不是自身的最优解,那么我们就可以从原问题中剪切掉这些非最优解,将最优解粘贴进去,从而得到原问题一个更优的解,这个解与最初的解的前提假设矛盾。
刻画子问题空间的经验
保持子问题空间尽量简单,只在必要时才扩展它。例如下一节的例子,求钢条切割的最大收益问题中,子问题空间包含的问题为:对每个i值,长度为i的钢条最优切割问题。
对于不同问题领域,最优子结构的不同体现在两个方面:
- 原问题的最优解中涉及到多个子问题。
- 在确定最优解使用哪些子问题时,需要考察多少种选择。
重叠子问题
适合用动态规划方法求解最优化问题的第二个性质是子问题的空间必须足够小,即问题的递归算法会反复地求解相同的子问题,而不是一直生成新的子问题。动态规划算法会对重叠的子问题只求解一次,并保存在一张表里,需要用的时候直接查表即可,每次查表的时间代价为常量O(1)。