第5章 贪心算法

贪心算法和动态规划算法有类似也有不同,动态规划算法需要遍历问题的所有可能性,而贪心算法不需要遍历,只需要取该步骤中最优的那一个
如矩阵乘法问题中,求A1-4的最优解如果用动态规划算法需要遍历:“(1)A1-3的最优解代价和A4的最优解代价和二者相乘的代价;(2)A1-2的最优解代价和A3-4的最优解代价和二者相乘的代价;(3)A1的最优解代价和A2-4的最优解代价和二者相乘的代价”,如果使用贪心算法,只需要求:“(1)A1-3A4的代价;(2)A1-2A3-4的代价;(3)A1*A2-4的代价”,也就是说,贪心算法只需要考虑划分问题这一步是否是最优,不需要考虑划分出的子问题是否是最优(贪心算法不需要计算比较A1-3的最优解代价和A4的最优解代价、A1-2的最优解代价和A3-4的最优解代价、A1的最优解代价和A2-4的最优解代价)

贪心算法的基本原理

贪心算法的基本思想

求解最优化问题的算法包含一系列步骤,每一步都有一组选择,作出在当前看来最好的选择,希望通过作出局部优化选择达到全局优化选择,贪心算法不一定总产生优化解,贪心算法是否产生优化解需严格证明

贪心算法产生优化解的条件

  1. 贪心选择性
    1. 若一个优化问题的全局优化解可以通过局部优化选择得到,则该问题称为具有贪心选择性
  2. 优化子结构
    1. 若一个优化问题的优化解包含它的子问题的优化解,则称其具有优化子结构

贪心算法正确性的证明

证明

  1. 证明算法所求解的问题具有优化子结构
  2. 证明算法所求解的问题具有贪心选择性
  3. 证明算法确实按照贪心选择性进行局部优化选择

优化证明

  1. 至少有一个最优解包含贪心选择(一般使用反证法(所有最优解均含贪心选择):假设存在最优解不含贪心选择,将此最优解中的一个选择替换为贪心选择后,得到一个更优解,与最优解矛盾;也可以直接找到含贪心选择的最优解(至少有一个最优解含贪心选择(见“任务安排问题”)):找到最优解的共有选择,将共有选择中的一个换为贪心选择后仍为最优解,换后的最优解即为含贪心选择的最优解)
  2. 1.中的最优解去掉贪心选择后,得到的解是某个子问题的最优解(一般使用构造法+反证法,先构造出符合的子问题,再使用反证法证明由原问题最优解得到的解是构造出的子问题的最优解:假设由原问题最优解得到的解不是子问题的最优解,那么子问题题存在更优解,将子问题的更优解与由原问题最优解得到的解回溯得到原问题的解,进而得到子问题的更优解的回溯优于由原问题最优解得到的解的回溯,与由原问题最优解得到的解的回溯是原问题的最优解矛盾)

说明:
**1.+2.可以得出具有优化子结构,1.+2.+数归可以得出具有贪心选择性,而一般情况下数归部分不用证,所以只用证明1.2.**即可

贪心算法的例子

任务安排问题

输入:S={1, 2, …, n},F={ [si,fi] },n≥i≥1
输出:S的最大相容集合

贪心思想

为了选择最多的相容活动,每次选fi最小的活动,使我们能够选更多的活动

正确性证明

普通证明

优化子结构
  1. 设S={1,2,…,n}是n个活动集合,[si,fi ]是活动的起始终止时间,且f1≤f2≤….≤fn,S的活动选择问题的某个优化解包括活动1(首先得证明至少有一个优化解包括贪心选择)
    image.png
  2. 设S={1,2,…,n}是n个活动集合,[si,fi]是活动i的起始终止时间,且f1≤f2≤….≤fn,设A是S的调度问题的一个优化解且包括活动1,则A’=A-{1}是S’={i∈S|si≥f1} 的调度问题的优化解(再证明包括贪心选择的优化解包含子问题的优化解)
    image.png
贪心选择性
  1. 注意与优化子结构的第一步区别,优化子结构的第一步是证明至少有一个优化解包含贪心选择,而贪心选择性是指优化问题的全局优化解可以通过局部优化选择得到(证明至少有一个优化解包含贪心选择还不行,还需要证明此优化解包含的子问题的优化解中至少有一个也包含贪心选择,子问题的优化解包含的子子问题的优化解中至少有一个也包含贪心选择……,这样才能保证全局优化解可以由贪心选择一步步选择得到(每一步选择都是贪心选择,最终的结果为优化解))
    image.png

哈夫曼编码问题

输入:字母表 C = {c1, c2, …, cn},频率表 F = {f(c1), f(c2), …, f(cn)}
输出:具有最小B(T)的C前缀编码树

定义

  1. 编码树
    image.png
  2. 编码树的代价
    image.png

贪心思想

  1. 循环地选择具有最低频率的两个结点,生成一棵子树,直至形成树
  2. 例如:C={f,e,c,b,d,a},F={f(f)=5,f(e)=9,f©=12,f(b)=13,f(d)=16,f(a)=45}
    image.png

正确性证明

优化证明

  1. 至少有一个最优解包含贪心选择
    image.png
    image.png
    image.png
    image.png
  2. 最优解去掉贪心选择后,得到的解是某个子问题的最优解
    image.png
    image.png
    image.png

最小生成树

输入:无向连通图G=(V, E), 权函数W
输出:G的最小生成树

Kruskal算法

基本思想:
  1. 将所有的边按照权值从小到大排序
  2. 从权值最小的边开始,依次考虑每一条边,如果该边的两个端点不在同一个连通分量中,就将其加入最小生成树中,并将这两个端点合并到同一个连通分量中(判断端点是否在同一个连通分量采用的数据结构是并查集)
  3. 重复步骤2,直到所有的边都被考虑过或者最小生成树中已经包含了所有的顶点
正确性证明

优化证明

  1. 至少有一个最优解包含贪心选择
    image.png
  2. 最优解去掉贪心选择后,得到的解是某个子问题的最优解
    image.png
    image.png

Prim算法

基本思想
  1. 首先任选一个顶点作为起点,将其加入已选顶点集合中
  2. 在当前已选顶点集合与未选顶点集合之间,找到权值最小的边,将其加入最小生成树中
  3. 将新加入的顶点加入已选顶点集合中,更新当前已选顶点集合与未选顶点集合
  4. 重复步骤2和步骤3,直到最小生成树包含所有顶点为止
正确性证明

优化证明

  1. 至少有一个最优解包含贪心选择
    image.png
  2. 最优解去掉贪心选择后,得到的解是某个子问题的最优解(与Kruskal的证明相同,只需要将紧缩的两个端点换为起点的最短边的两个端点)

如果你喜欢这篇文章,别忘了点点赞和收藏🥰
更多内容及实时更新请访问笔者语雀知识库,本篇内容可在第5章 贪心算法查看(打开文档后点击右上角演示可获得更好的阅读效果哦~)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你才是猪头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值