动态规划原理
-
基本思想:问题的最优解如果可以由子问题的最优解推导得到,则可以先求解子问题的最优解,在构造原问题的最优解;若子问题有较多的重复出现,则可以自底向上从最终子问题向原问题逐步求解。
-
动态规划算法的设计步骤:
- 分析优化解的结构
- 递归地定义最优解的代价
- 自底向上地计算优化解的代价保存之,并获取构造最优解的信息
- 根据构造最优解的信息构造优化解
-
动态规划特点:
- 把原始问题划分成一系列子问题;
- 求解每个子问题仅一次,并将其结果保存在一个表中,以后用到时直接存取,不重复计算,节省计算时间
- 自底向上地计算
- 整体问题最优解取决于子问题的最优解(状态转移方程)(将子问题称为状态,最终状态的求解归结为其他状态的求解)
-
使用条件:*可分为多个相关子问题,子问题的解被重复使用*
-
最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。
-
Optimal substructure(优化子结构):
- 一个问题的优化解包含了子问题的优化解
- 缩小子问题集合,只需那些优化问题中包含的子问题,降低实现复杂性
- 可以自下而上的
-
有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)
-
Subteties(重叠子问题):在问题的求解过程中,很多子问题的解将被多次使用。
-
无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。
-
-
例题:
- 矩阵连乘问题
- 最长公共子序列
- 多边形游戏
- 图像压缩…
分治算法
-
基本思想:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题。这些子问题互相独立且与原问题形式相同,递归地独立解这些子问题,然后将各子问题的解合并得到原问题的解,这种算法设计策略叫做分治法。
-
如果原问题可分割成k个子问题,1<k≤n,且这些子问题都可解并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。
-
分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解,这自然导致递归过程的产生。
-
适用情况
- 子问题与原始问题性质完全一样
- 子问题之间可以独立求解
- 递归停止时,子问题可直接求解
-
基本步骤
- 将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
- 若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
- 将各个子问题的解合并为原问题的解。
-
复杂度分析
-
Master Theorem
-
T ( n ) = a T ( n / b ) + f ( n ) T(n)=aT(n/b)+f(n) T(n)=aT(n/b)+f(n)
-
- n是问题规模大小
- a是原问题的子问题个数
- n/b是每个子问题的大小,这一的引用理论在于每个子问题的规模大小一样
- f(n)表示的是将原问题分解成子问题和将子问题合并为原问题的解的时间
-
应用说明:
- 用
n
l
o
g
b
a
n^{log_b^a}
nlogba(A)与
f
(
n
)
f(n)
f(n)(B)两者做比较做时间复杂度分析
- A更大时有 T ( n ) = Θ ( n l o g b a ) T(n)=\varTheta(n^{log_b^a}) T(n)=Θ(nlogba)为递归式的时间复杂度分析结果
- B更大时,且af(n/b)<=cf(n),有 T ( n ) = Θ ( f ( n ) ) T(n)=\varTheta(f(n)) T(n)=Θ(f(n))为递归式的时间复杂度分析结果
- 当A=B时,则有 T ( n ) = Θ ( n l o g a b l o g k + 1 n ) T(n)=\varTheta(n^{log_a^b}{log^{k+1}{n}}) T(n)=Θ(nlogablogk+1n)为递归式的时间复杂度分析结果
- 用
n
l
o
g
b
a
n^{log_b^a}
nlogba(A)与
f
(
n
)
f(n)
f(n)(B)两者做比较做时间复杂度分析
-
-
-
例题:
- 棋盘覆盖问题
- 快速排序
- 大整数的乘法
- 最接近点对问题…
动态规划和分治法的区别
- 动态规划也是一种分治思想(比如其状态转移方程就是一种分治),但与分治算法不同的是
- 分治算法是把原问题分解为若干个子问题,自顶向下求解子问题,合并子问题的解,从而得到原问题的解。
- 动态规划也是把原始问题分解为若干个子问题,然后自底向上,先求解最小的子问题,把结果存入表格中,在求解大的子问题时,直接从表格中查询小的子问题的解,避免重复计算,从而提高算法效率。