我们之前探讨过的很多算法都利用问题的可规划性以及子问题之间的相似性来进行归纳,降低求解的复杂度,动态规划也不例外。动态规划算法把原问题视作若干个重叠子问题的逐层递进,每个子问题的求解过程都构成一个”阶段“。在完成前一个阶段的计算后,动态规划才会执行下一阶段的计算。
为了保证这些计算能够按顺序、不重复地进行,动态规划要求已经求解的子问题不受后续阶段的影响。这个条件也被叫做”无后效性“。换言之,动态规划对状态空间的遍历构成一张有向无环图,便利顺序就是该有向无环图的一个拓扑序。有向无环图中的节点对应问题中的”状态“,图中的边则是对应状态的”转移“,转移的选取就是动态规划中的”决策“。
很多情况下,动态规划用于求解最优化问题。此时,下一阶段的最优解应该能由前面个阶段子问题的最优解导出。这个条件被称为”最优子结构性质“。当然,这是种比较片面的说法,他其实告诉我们,动态规划在阶段计划完成时,只会在每个状态上保留与最终题解相关的部分代表信息,这些代表信息应该具有可重复的求解过程,并能够导出后续阶段的代表信息。这样一来,动态规划对状态的抽象和子问题的重叠递进才能起到优化作用。
”状态“”阶段“和“决策”是构成动态规划算法的三要素,而“子问题重叠性”“无后效性”和”最优子结构性质“是问题能用动态规划求解的三个基本条件。
动态规划算法把相同的计算过程作用于各阶段的同类子问题,就好像把一个固定的公式在格式相同的若跟输入数据上运行。因此,我们一般只需要定义出DP计算过程,就可以编程实现了。这个计算过程就被称为”状态转移方程“。在大多数例中,我们讨论状态转移方程的设计思路,并给出最终的方程、边界和目标,而不再讨论程序的实现细节。