算法导论-动态规划原理

Posted Tommyplayer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法导论-动态规划原理相关的知识,希望对你有一定的参考价值。

算法导论-动态规划原理

1. 动态规划的概念

  • 动态规划 (dynamic programming) 与分治方法相似,都是通过组合子问题的解来求解原问题(programming 指的是一种表格法,并非编写计算机程序。

  • 动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题(子问题的求解是递归进行的,将其划分为更小的子子问题)。动态规划对每个子子问题只求解一次,将其解保存在一个表格中,从而无需每次求解一个子子问题都重新计算,避免了这种不必要的计算工作。

  • 动态规划常用来求解最优化问题 (optimization problem)。这类问题有很多可行解,动态规划可以寻找到具有最优值(最大值或最小值)的解。这样的解为问题的一个最优解,而不是最优解,因为可能有多个解都达到最优值。

2. 动态规划的基本步骤和性质

2.1 基本步骤

  1. 刻画一个最优解的结构特征(将原问题划分为子问题)。
  2. 利用子问题的最优解递归地定义最优解的值(递推公式)。
  3. 计算最优解的值,通常采用自底向上的方法。
  4. 利用计算出的信息构造一个最优解。

2.2 性质

  1. 两种方法:带备忘的自顶向下 (top-down)法;自底向上 (bottom-up)法

  2. 动态规划的标识:最优子结构,子问题重叠

    • 最优子结构

      一个问题的最优解包含子问题的最优解,问题的最优解由子问题的最优解组合而成,而这些子问题可以独立求解。

      做出一次选择,做出这次选择后会产生一个或多个待解的子问题;如何最好地刻画子问题空间(变量个数,具体表现在 dp 数组的维度);考察多种选择中选择最优解。

    • 子问题无关:同一个原问题的子问题的解不影响另一个子问题的解。

    • 子问题重叠:递归算法重复求解相同的子问题。

    • 重构最优解:我们将每个子问题所作出的选择存入一个表中,这样就不必根据代价值来重构这些信息。

    • 如果每个问题都至少要求解一次,自底向上比备忘录快。如果子问题空间中的某些问题完全不必求解,则备忘方法快。

3. 最优子结构 (Optimal substructure)

  • 最优子结构并不适用于所有最优化问题。

    最短路径问题具有最优子结构的性质,但最长简单路径问题不具有这种性质。

    例子:给定一个有向图 G = (V,E) 和 一对结点 u 和 v ,如果 p = p1p2 是从 u 到 v 的最短路径,那么 p1 是从 u 到 w 的最短路径。

证明如下:

如果存在另外一条从 u 到 w 的最短路径,叫做 p’1,那么 p‘1p2 这条路径的长度小于 p1p2 的长度,这就与假设矛盾。

  • 子问题无关:同一个原问题的一个子问题的解不影响另一个子问题的解。

    最短路径问题的子问题是无关 (independent) 的。

    如果 (p1 = uw) (p2 = wv) 是最短路径,那么 p1 和 p2 除了 w 不能再有其他公共顶点。

  • 最优子结构的体现:

    1. 原问题的最优解涉及多少个子问题
    2. 在确定最优解使用哪些子问题时,我们需要考察多少种选择

4. 重叠子问题 (Overlapping Subproblems )

5. 无后效性

这里参考了 leetcode 作者 liweiwei1419 的题解

一个问题的递归结构如下图所示(这里忽略问题场景)。

可以发现有重复求解的部分,需要添加缓存,这是「记忆化递归」。

另外还可以从通过发现一个问题最开始的样子,通过「递推」一步一步求得原始问题的解,此时求解的过程如下图所示:

箭头指向的地方表示当前求解的过程中参考了以前求解过的问题的结果,这个过程不能形成回路,形成回路就无法求解

6. 经典问题

  1. 装配线调度(Assembly-Line Scheduling)
  2. 钢条切割
  3. 矩阵链乘法
  4. 最长公共子序列(Longest Common Subsequence,LCS)
  5. 旅行商问题(TSP)
  6. 最优二叉搜索树

以上是关于算法导论-动态规划原理的主要内容,如果未能解决你的问题,请参考以下文章

算法导论_第十六章_动态规划_creatshare分享会

《算法导论》中动态规划求解钢条切割问题

算法导论精华总结 ~ 动态规划

算法导论之动态规划 字符串拆分问题

算法导论—矩阵链乘法(动态规划)

算法导论_动态规划_最长公共子序列