//整理笔记之算法部分。。。for_wind
1、动态规划
动态规划适用于子问题不是独立的情况,也就是各子问题包含公共的子子问题。动态规划算法对每个子子问题只求解一次,将其结果保存在一张表中,从而避免每次遇到各个子问题时重新计算答案。
如:装配线调度、矩阵链成法、最长公共子序列、最优二叉查找树。
- 动态规划算法的设计分如下4个步骤:
1、描述最优解的结构;2、递归定义最优解的值;(得到递归式)3、按自底向上的方式计算最优解的值;4、由计算出的结果构造出一个最优解。
- 动态规划方法的最优化问题中的两个要素:最优子结构和重叠子问题。
- 最优子结构
- 寻找最优子结构时候,可以遵循一种共同的模式:
- 问题的一个解可以是做一种选择。做这种选择会得到一个或多个有待解决的子问题。
- 假设对一个给定的问题,已知的是一个可以导致最优解的选择。不必关心如何确定这个选择,尽管假定它是已知的。
- 在已知这个选择后,要确定哪些子问题会随之发生,以及如何最好地描述所得到的子问题空间。
- 利用一种“剪贴”技术,来证明问题的一个最优解中,使用的子问题的解本身也必须是最优的。
- 最优子结构在问题域以两种方式变化:
- 有多少子问题被使用在原问题的一个最优解中,以及
- 在决定一个最优解中使用哪些子问题时有多少个选择。
动态规划以自底向上的方式来利用最优子结构。首先找到子问题的最优解,解决子问题,然后找到问题的一个最优解。寻找问题的一个最优解需要在子问题中做出选择,即选择哪一个来求解问题。问题解的代价通常是子问题的代价加上选择本身带来的开销。
贪心算法是以自顶向下的方式来使用最优子结构。贪心算法先做选择,在当时看来是最优的选择,然后再求解一个结果的子问题,而不是先寻找子问题的最优解,然后再做选择。
贪心算法是以自顶向下的方式来使用最优子结构。贪心算法先做选择,在当时看来是最优的选择,然后再求解一个结果的子问题,而不是先寻找子问题的最优解,然后再做选择。
- 重叠子问题
- 动态规划要求子问题既要独立又要重叠。即:同一个问题的两个子问题不共享资源(独立),同一个子问题会作为不同问题的子问题出现(重叠)。
- 做备忘录(动态规划的变形):
2、贪心算法
- 贪心算法:活动选择问题;任务调度问题;数据压缩(huffman)编码的设计;最小生成树;Dijkstra的单源最短路径。
- 贪心算法的设计步骤:
- 将优化问题转换成这样的一个问题:即先做出选择,再解决剩下的子问题。
- 证明原问题总是由一个最优解是做贪心选择得到的,从而证明贪心选择的安全性。
- 说明在做出贪心选择后,剩余的子问题具有这样的一个性质。即如果将子问题的最优解和我们所做的贪心选择联合起来后,可以得出原问题的一个最优解。
- 贪心选择性质:
贪心选择的性质:一个全局最优解可以通过局部最优(贪心)选择来达到。换句话说,当考虑做如何选择时候,我们只考虑对当前问题最佳的选择而不考虑子问题的结果。- 以上这一点是贪心算法不同与动态规划之处:
- 在动态规划中,每一步都要做出选择,但是这些选择依赖于子问题的解。因此解动态规划问题一般是自底向上,从小子问题处理至大子问题。
- 在贪心算法中,我们所做的总是当前看似最佳的选择,然后在解决选择之后所出现的子问题。贪心算法年所做的当前选择可要依赖于已经做出的所有选择,当不依赖于有待做出的选择或子问题的解。贪心策略通常是自顶向下地做的,一个一个的做出贪心选择,不断的将给定的问题实例规约为更小的问题。
- 贪心算法使用最优子结构,通常是更加直接的方式。假设原问题做了一个贪心选择而得到一个子问题。真正要做的是证明此子问题的最优解与所做的贪心选择合并后,的确可以得到原问题的一个最优解。
- 0-1背包和部分背包问题:
0-1背包之为什么不能用贪心算法解决?
因为当无法将背包填满,空余的空间降低了该背包内货物的有效单位价值。
在0-1背包问题中,当我们在考虑是否要把一件物品加到背包中时,必须对把该物品加进去的子问题的解与不取该物品的子问题的解进行比较。导致许多重叠子问题,可以采用动态规划来解决。