动态规划

动态规划

20世纪50年代初,美国数学家R.Bellman等在创立了动态规划(Dynamic Programming),用于解决多阶段决策过程的问题。所以动态规划最早是应用数学、运筹学中的概念,并非算法概念。在用动态规划策略解决问题时,解题者需要先把问题拆分成有序的多个“阶段”,这些“阶段”的“形式”通常一样。后面的“阶段”的解可以根据前面若干个不同“阶段”的解来确定,但不能被更后面的“阶段”的解所决定(这也称为无后效性)。这种关系需要被描述成通常包含递推函数的“状态转移方程”。借助状态转移方程,就能依次得到每个“阶段”的解,最终得到问题的解。可以发现,“阶段”就类似分治法中的“子问题”,“状态转移方程”就类似解决“子问题”的递归程序,所以动态规划和分治法的策略框架基本一样,也可能分治法外延更广一点。

在算法的语境下,可以直接把动态规划策略看作一种关于“如何物理实现分治策略”的策略。一般的分治算法默认用自顶向下的递归程序实现。而在动态规划算法中,会自底向上的先从解最小的子问题开始,逐步的求出更大的“子问题”,最终得到原问题的解。实现这一点的最常见的方法是额外建立一个数据结构,用来缓存之前求过的子问题的“输入-输出(解)”,这样之后的“子问题”需要前面的“子问题”的解时,就直接去这个数据结构中取。

总而言之,分治和动态规划可以看作是同一算法策略的不同实现。当算法策略中经常出现对同一子问题(输入相同)的计算时(称为存在大量重叠子问题),动态规划因为能缓存子问题的结果,所以能避免重复计算,效率更高,很多时候甚至可以有更低的时间复杂度。但在没有重叠子问题时,动态规划因为额外维护了缓存,可能会比分治算法有更高的空间复杂度。并且如果能够精心的优化该额外数据结构、设计迭代次序,有时还能有更优的时间复杂度。

值得注意的是动态规划算法定义的子问题的解通常是“值”,但分治算法中所定义的子问题的解可以是各种形式。因为在动态规划中,子问题间的递推关系是先用状态转移方程描述,而后再将方程转化为程序。分治算法则直接把这个递推关系写成程序。如果动态规划中子问题的解不是数值,而是数组什么的,理论上也没问题,但状态转移方程可能会十分繁琐。所以通常在确定要用动态规划解决问题时,会想办法先把问题先做一些“转化”,使得子问题的解是数值。也有很多人认为修改分治算法,使其有缓存子问题解的能力,得到的新算法也属于动态规划算法,称为带“备忘录”的分治算法。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部