1、两种重要算法思想: 动态规划,贪心算法
2、动态规划:
基本原理:动态规划英文名dynamic programming。其中pogramming指的是表格法,而非编写计算机程序。因此,可以初步得出动态规划的基本思想:将一个具有最优子结构性质的问题分成若干个子问题,在求解过程中,记录下子问题的结果,存储在一个表格中,使得公共的子问题只需要计算一次。书中给出的基本原理:动态规划将问题分成若干个相互重叠的子问题,递归的求解子问题,保存子问题的解,再将它们的解组合起来,求出原问题的解。
从基本原理中可以看出动态规划需要满足两个条件,最优子结构和子问题重叠。
最优子结构:书中定义:问题的最优解由相关子问题的最优解组合而成,一个问题的最优解包含其子问题的最优解。典型的有背包问题和钢条切割我问题。所谓子问题就是一中组合,将一个问题分成许多子问题的集合。某个子问题转化为问题时,所需要的代价是固定的。
一般这类问题的解题过程:(自己总结)
画出子问题图(类似于逆拓扑排序的图,子问题必须在问题前面完成)
用数学表达式构建出问题的最优解和子问题最优解之间的代数表达式
通常采用自底向上的方法进行递归地求解问题的解,自底下上的含义是从最小的子问题求起。
保存每一步求出的子问题的最优解
利用计算出的信息构造一个最优解
3、贪心算法:
基本原理:从初始状态出发,每步都经过贪心选择,最终得到问题的最优解。
含义: 将每一步都看成是当前最佳的选择,做到局部最优化,直到无法选择为止。寄希望于局部最优的选择能够导致全局最优解。
两个实例:最小生成树算法和单源最短路径算法,以及集合覆盖问题的贪心启发式算法。
prim算法:将集合A看成是一棵树,每次选择剩余的节点中与这棵树形成的边的权值最小的点加入到集合A中形成新的树,循坏调用该过程,知道所有的点都已经放入到集合A中。初始时随机选择一个节点放入到集合A中。
kruskal算法:在所有连接森林中两颗不同树的边里面,找到权重最小的边(u,v),并将其加入到集合A中,循环调用该过程,直到所有的点已经放入到集合A中
贪心选择:当进行选择时,我们直接作在当前问题看来是最优的选择,而不必考虑子问题的解。这与动态规划不同,动态规划当前问题依赖于较小的子问题。而贪心算法中做当前问题最优选择,这样每步之后只需要做一个子问题的解。
也必须满足最优子结构的性质,即一个问题的最优解包含其子问题的最优解。
那么,如何区分什么时候使用动态规划,什么时候使用贪心算法呢?
典型的两个问题,0-1背包和分数背包。两者都具有最优子结构性质,但是贪心算法只能用来求分数背包的问题,而不能用来求0-1背包的问题。即只有分数背包具有贪心选择性。
我得总结(不一定对):具有贪心选择性的一类问题是:每次做选择时只有性能不同,而代价是一样的。那么这样每次的选择都是最好的,最终会得到最好的结果。
哈夫曼编码也使用贪心选择算法。每次选择待编码的字符都选择在剩余的字符中出现次数最多的