Data Structures Algorithms 简明教程

Dynamic Programming

动态规划方法类似于分而治之,将问题分解为更小且更小的可能子问题。但与分而治之不同,这些子问题不是独立解决的。相反,这些较小子问题的结果会被记住并用于解决相似的或重叠的子问题。

通常,动态规划算法用于解决优化问题。在解决手头的子问题之前,动态算法将尝试检查以前已解决的子问题的结果。子问题的解会结合在一起以便获得最佳的最终解。因此,这种范式被称为使用自底向上的方法。

所以我们可以得出以下结论:

  1. 该问题应该能够被分成较小的重叠子问题。

  2. 可以通过使用较小子问题的最优解来获得最终的最优解。

  3. Dynamic algorithms use memorization.

dynamic programming approach

然而,在一个问题中,两个主要属性可以表明给定问题可以使用动态规划来解决。它们是:

Overlapping Sub-Problems

与分而治之的方法类似,动态规划也结合了子问题的解。它主要用于重复需要一个子问题的解的情况。已计算的解会存储在一个表中,这样无需重新计算它们。因此,当存在重叠子问题时就需要这种技术。

例如,二分查找没有重叠子问题。然而,斐波那契数的递归程序有许多重叠子问题。

Optimal Sub-Structure

如果给定问题的最优解可以使用其子问题的最优解获得,则给定问题具有最优子结构属性。

例如,最短路径问题具有以下最优子结构属性:

如果一个节点 x 位于从源节点 u 到目标节点 v 的最短路径中,则从 uv 的最短路径是从 u 到 x 的最短路径和从 x 到 v 的最短路径的组合。

标准的全对最短路径算法,如 Floyd-Warshall 和 Bellman-Ford,是动态规划的典型示例。

Steps of Dynamic Programming Approach

动态规划算法是使用以下四个步骤设计的:

  1. 描述最优解的结构。

  2. 递归定义最优解的值。

  3. 计算最优解的值,通常采用自底向上的方式。

  4. 从已计算的信息中构建一个最优解。

Dynamic Programming vs. Greedy vs. Divide and Conquer

与贪心算法(着重于局部优化)不同,动态算法的目的是对问题进行整体优化。

与分治算法(将解组合在一起以达到最终解)不同,动态算法使用子问题的结果,然后尝试优化更大的子问题。动态算法利用记忆化来记住已解决子问题的输出。

Examples of Dynamic Programming

以下计算机问题可以使用动态规划方法解决 −

动态规划可以按照自顶向下和自底向上的方式使用。当然,大多数时候,参考之前的解输出比在 CPU 周期方面重新计算更便宜。