1、贪心算法,陈阳,定义,贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解,生活中的例子,例如:在买东西时,售货员就常常计算最少需要找多少张零钱,以便简化工作流程。比如买东西需要48.5元,交给售货员100元整,按照现在的货币体系,则售货员最少需要找三张零钞:50元一张、1元一张、5角一张。,贪心算法的基本思路,贪心算法的基本思路如下: 1)建立数学模型来描述问题。 2)把求解的问题分成
2、若干个子问题。 3)对每一子问题求解,得到子问题的局部最优解。 4)把子问题的解局部最优解合成原来解问题的一个解。,贪心算法找最优解的必要条件,第一,原问题具有最优子结构。这样才能得到局部最优解。 第二,原问题的最优解包含了它子问题的最优解。 这样才能由局部最优合成全局最优,并且局部最优解一旦获得就不会改变。,石子合并问题,在一个操场的四周摆放 N 堆石子,现要将石子有次序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数记为该次合并的得分。已知每堆石子数量,请选择一种合并石子的方案,使得进行N-1次合并得分的总和最小。,石子合并问题,对于这个问题,很人都会选择贪心算法
3、求解即每次选相邻和最小的两堆石子合并。对于上面的图例,利用此贪心策略的确可以找到最优解。然而本题给的样例数据实际上是一个“陷阱”,造成了用贪心法即可解决的假象。,2+3=5 5+4=9 5+4=9 9+6=15 15+9=24 总数:5+9+15+24+9=62,2+4=6 3+4=7 6+7=13 5+6=11 13+11=24 总数:6+7+13+24+11=61,背包问题,有一个背包,背包容量是M=150。有7个物品,物品不可以分割成任意大小。 要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。 物品 A B C D E F G 重量 35 30 60 50 40 10 25 价
4、值 10 40 30 50 35 40 30,背包问题,目标函数: pi最大 约束条件是装入的物品总重量不超过背包容量:wi=M( M=150) (1)根据贪心的策略,每次挑选价值最大的物品装入背包,得到的结果是否最优? (2)每次选取单位重量价值最大的物品,成为解本题的策略。,背包问题,(1)贪心策略:选取价值最大者。 反例: M=30 物品:A B C 重量:28 12 12 价值:30 20 20 根据策略,首先选取物品A,接下来就无法再选取了,可是,选取B、C则更好。,背包问题,(2)贪心策略:选取单位重量价值最大的物品。 反例: W=30 物品:A B C 重量:20 15 15 价
5、值:40 25 25 根据策略,三种物品单位重量价值一样,程序无法依据现有策略作出判断,如果选择A,则答案错误。,哈夫曼树和哈夫曼编码,设计二进制编码方案时要考虑不同字符的使用频率,使用频率高的字符编码应当尽量短一些。但是仅仅考虑使用频率也是不够的。例如:某个文件由A、B、C、D四个字符组成,其中A用得最多,C次之。 方案1: A 1 C 0 B 10 D 11 那么象1100这样的二进制数据具有二义性,既代表AACC,又可代表ABC,还可代表DCC。为了不使二进制编码具有二义性,每个字符编码都不能与其他字符编码的前面若干位重合。,哈夫曼树和哈夫曼编码,可以利用二叉树分析字符编码问题。假设二叉
6、树中的左分支代表0,右分支代表1,则不论字符是采用何种0、1组合形式构成的编码,它必然对应某个二叉树中一个结点。,(a)有二义性的编码系统对应的二叉树 (b)无二义性的编码系统对应的二叉树,任何一个无二义性的二进制字符编码系统必然与这样一颗二叉树对应,该二叉树的叶子结点对应着所有需要转换的字符,并且按照左分支代表0、右分支代表1的规则,从根到该叶子的分支对应的0、1序列就构成叶子对应字符的二进制编码。,哈夫曼树和哈夫曼编码,二叉树带权路径长度:设二叉树有n个带有权值的叶子结点,每个叶子到根的路径长度乘以其权值之和称为二叉树带权路径长度。一般记作:其中,wi为第i个叶子的权重,li为第i个叶子到
7、根的路径长度。哈夫曼树:以一些带有固定权值的结点作为叶子所构造的,具有最小带权路径长度的二叉树称为哈夫曼树。,利用贪心算法构建哈夫曼树,将权值最小的两个结点作为左、右孩子合并为一颗二叉树。它们在将来的合并中将被放到离根结点最远的层次。,假定一段报文由a、b、c、d四个字符构成,它们的使用频率比为3:3:2:1,那么第一步应将权值最小的c和d作为左右孩子合并为一颗二叉树,如图4-41的步骤1所示。,利用贪心算法构建哈夫曼树,第一步做完后,图4-41的初始状态变为图4-41步骤1的形式。为了进一步合并,可以将c、d合成的树作为一个整体“结点”看待。换言之,可以将c、d的权值之和放到这棵树的根结点,而后在a、b和这个根结点之间进一步合并,合并策略与上面的步骤相同。贪心策略可描述为:将根结点权值最小的两颗二叉树作为左、右孩子合并为一颗二叉树。并重复这一过程直到所有结点均合并在一起。,谢谢,