**动态规划**（英語：，简称）是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的，通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。

动态规划常常适用于有重叠子问题和最优子结构（英语：）性质的问题，动态规划方法所耗时间往往远少于朴素解法。

动态规划背后的基本思想非常简单。大致上，若要解一个给定问题，我们需要解其不同部分（即子问题），再根据子问题的解以得出原问题的解。

通常许多子问题非常相似，为此动态规划法试图仅仅解决每个子问题一次，从而减少计算量：一旦某个给定子问题的解已经算出，则将其记忆化存储，以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指數增長时特别有用。

概述
--

动态规划在查找有很多**重叠子问题**的情况的最优解时有效。它将问题重新组合成子问题。为了避免多次解决这些子问题，它们的结果都逐渐被计算并被保存，从简单的问题直到整个问题都被解决。因此，动态规划保存递归时的结果，因而不会在解决同样的问题时花费不必要的时间。

动态规划只能应用于有**最优子结构**的问题。最优子结构的意思是局部最优解能决定全局最优解（对有些问题这个要求并不能完全满足，故有时需要引入一定的近似）。简单地说，问题能够分解成子问题来解决。

适用情况
----

1. 最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的，我们就称该问题具有最优子结构性质（即满足最优化原理）。最优子结构性质为动态規劃算法解决问题提供了重要线索。
2. 无后效性。即子问题的解一旦确定，就不再改变，不受在这之后、包含它的更大的问题的求解决策影响。
3. 子问题重叠性质。子问题重叠性质是指在用递归算法自顶向下对问题进行求解时，每次产生的子问题并不总是新问题，有些子问题会被重复计算多次。动态規劃算法正是利用了这种子问题的重叠性质，对每一个子问题只计算一次，然后将其计算结果保存在一个表格中，当再次需要计算已经计算过的子问题时，只是在表格中简单地查看一下结果，从而获得较高的效率，降低了时间复杂度。

实例
--

包括但不限于切割钢条问题、Floyd最短路问题、最大不下降子序列、矩阵链乘、凸多边形三角剖分、背包问题、最长公共子序列、最优二分搜索树等。

#### 背包问题

背包问题作为NP完全问题，暂时不存在多项式时间算法。动态规划属于背包问题求解最优解的可行方法之一。此外，求解背包问题最优解还有搜索法等，近似解还有贪心法等，分数背包问题有最优解等。
背包问题具有最优子结构和重叠子问题。动态规划一般用于求解背包问题中的整数背包问题（即每种物品所选的个数必须是整数）。
解整数背包问题：
设有{\displaystyle n}件物品，每件价值记为{\displaystyle P\_{i}}，每件重量记为{\displaystyle W\_{i}}，用一个最大重量为{\displaystyle W}的背包，求装入物品的最大价值。
在总重量不超过*W*的前提下，我们希望总价格最高。对于*Y* ≤ *W*，我们将在总重量不超过*Y*的前提下，总价格所能达到的最高值定义为*A*(*Y*)。*A*(*W*)即为问题的答案。

显然，*A*(*Y*)满足：

* *A*(0) = 0
* *A*(*Y*) = max { *A*(*Y - 1*), { *pj* + *A*(*Y* - *wj*) | *wj* ≤ *Y* } }

其中，*pj*为第*j*种物品的价格。

对于特例0 1背包问题（即每件物品最多放1件，否则不放入）的问题，我们将在总重量不超过*Y*的前提下，前*j*种物品的总价格所能达到的最高值定义为*A*(*j*, *Y*)。

*A*(*j*, *Y*)的递推关系为：

* *A*(0, *Y*) = 0
* 如果*wj* > *Y*, *A*(*j*, *Y*) = *A*(*j* - 1, *Y*)
* 如果*wj* ≤ *Y*, *A*(*j*, *Y*) = max { *A*(*j* - 1, *Y*), *pj* + *A*(*j* - 1, *Y* - *wj*)}

参考Pascal代码

```
for i:=1 to n do
 for v:=totv downto v[i] do
 f[v]:=max(f[v],f[v-v[i]]+p[i]);
writeln(f[totv]);

```

参考C++代码（不含include和数组声明）

```
#define max(x,y) (x)>(y)?(x):(y) //max宏函数，也可以自己寫或者使用algorithm
for(int i=1;i<=n;i++)
 for (v=totv;v>=v[i];v--)
 f[v]=max(f[v],f[v-v[i]]+p[i]);
printf("%d",f[totv]); //或std::cout<<f[totv];

```

历史
--

术语"动态规划"最初是在 1940 年代由 理查德·贝尔曼 用来描述解决问题的过程，在这个过程中，人们需要一个接一个地找到最佳决策。到 1953 年，他将其精炼成为现代的含义，特别是指将较小的决策问题嵌套在较大的决策中， 并且该领域随后被电气电子工程师学会认可为系统分析和工程学主题。贝尔曼的贡献以贝尔曼方程的名义被铭记，它是动态规划的核心结果，它以递归 (计算机科学)形式重申了优化问题。

贝尔曼选择了"动态"这个词来捕捉问题的随时间变化的方面，也因为它听起来令人印象深刻。 "规划"一词指的是使用该方法来找到最佳的"程序"，在于军事训练或后勤计划的意义。这种用法与短语"线性规划"和"数学规划"中的用法相同。

术语起源的上述解释是不足的。正如罗素和诺维格在他们的书中提到上述故事时所写的那样："这不可能完全正确，因为他的第一篇使用这个词（贝尔曼，1952）的论文出现在威尔逊于 1953 年成为国防部长之前。"此外，还有Harold J. Kushner （页面存档备份，存于）在演讲中的评论，他记得贝尔曼。他在谈到贝尔曼时引用库什纳的话："另一方面，当我问他同样的问题时，他回答说他试图通过加上动态来超越乔治·伯纳德·丹齐格的线性规划。也许这两种动机都是正确的。"

使用动态规划的算法
---------

* 最长公共子序列
* Floyd-Warshall算法
* Viterbi算法
* Kadane's\_algorithm
* 求解馬可夫決策過程下最佳策略
* 萊文斯坦距離

外部链接
----

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
算法 |
| --- |
|  |
| 排序 | 

|  |  |
| --- | --- |
| 比较排序 | 
* 冒泡排序
* 选择排序
* 插入排序
* 希尔排序
* 快速排序
* 归并排序
* 堆排序
* 鸡尾酒排序
* 梳排序
* 侏儒排序
* 图书馆排序
* 内省排序
* 奇偶排序

 |
|  |
| 线性时间排序 | 
* 鸽巢排序
* 基数排序
* 計數排序
* 桶排序

 |
|  |
| 并行排序 | 
* 排序网络（英语：）
* Batcher归并网络

 |
|  |
| 不实用的 | 
* Bogo排序
* 臭皮匠排序

 |
|  |
| 图 | 
* 拓撲排序

 |

 |
|  |
| 搜索 | 

|  |  |
| --- | --- |
| 列表 | 
* 线性搜索
* 二分搜索
* 插值搜尋

 |
|  |
| 树・图 | 
* 广度优先搜索
	+ 最良優先搜索（英语：）
	+ 均一开销搜索
	+ A\*
* 深度优先搜索
	+ 迭代深化深度优先搜索
	+ 深度限制搜索（日语：）
	+ 双向搜索
* 分枝限定法（英语：）

 |
|  |
| 字符串 | 
* KMP算法
* 博耶-穆尔字符串搜索算法
* AC自动机算法
* 拉宾-卡普算法
* bitap算法

 |

 |
|  |
| 最短路问题 | 
* 戴克斯特拉算法
* 贝尔曼-福特算法
* A\*搜尋演算法
* Floyd-Warshall算法

 |
|  |
| 最小生成树 | 
* 普林姆算法
* 克鲁斯克尔演算法

 |
|  |
| 最大流最小割 | 
* 福特-富尔克森算法
* 埃德蒙兹-卡普算法
* 迪尼茨算法

 |
|  |
| 线性规划 | 
* 单纯形法
* 卡马卡尔算法（英语：）

 |
|  |
| 順序統計量 | 
* 选择算法
* 中位数的中位数（英语：）

 |
|  |
| 種類 | 
* 精确算法
* 近似算法
* 随机化算法

 |
|  |
| 其他 | 
* 分治法
* 动态规划
* 贪心算法

 |
|  |
| **Category:算法** |

 |

|  |  |  |
| --- | --- | --- |
| 

|  |  |
| --- | --- |
| 规范控制 編輯維基數據鏈接 | 
* BNE: XX543843
* BNF: cb11978098s (data)
* GND: 4125677-3
* J9U: 987007567971605171
* LCCN: sh85040313
* NDL: 00571739

 |

 |