计算机算法设计与分析第四章思维导图&&知识点总结

复习链接

计算机算法设计与分析第一章思维导图
计算机算法设计与分析第二章思维导图&&知识点总结
计算机算法设计与分析第三章思维导图&&知识点总结
计算机算法设计与分析第四章思维导图&&知识点总结
计算机算法设计与分析第五章思维导图&&知识点总结 ( 初稿 )
计算机算法设计与分析第六章思维导图&&知识点总结 ( 初稿 )
计算机算法设计与分析第七章思维导图&&知识点总结 ( 初稿 )

思维导图

在这里插入图片描述
( 注:对应用范例,本文最后一部分给出了部分思路 )

贪心算法的概念

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。

贪心算法的基本要素

(1)贪心选择性质

一个问题的整体最优解可通过一系列局部的最优解的选择得到,并且每次的选择可以依赖以前作出的选择,但不依赖于后面要作出的选择。这就是贪心选择性质。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每步所做的贪心选择最终导致问题的整体最优解。首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明,通过每一步做贪心选择,最终可得到问题的整体最优解。其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于,利用该问题的最优子结构性质。

(2)最优子结构性质

当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。

贪心算法与动态规划的差异

贪心策略:
在每一步中选择
在解子问题之前做出选择
每步选择,只看当前最佳,依赖之前的选择,与之后的选择无关
局部最优即全局最优
自顶向下解决问题

动态规划:
在每一步中做选择
选择依赖于子问题的最优解,故要先解决子问题
自底向上解决问题

动态规划算法中,每步所做的选择往往依赖于相关子问题的解。因而只有在解出相关自子问题后,才能做出选择。而在贪心算法中,仅在当前状态下做出最好选择,即局部最优选择。再去解做出这个选择后产生的相应子问题。贪心算法所作的贪心选择可以依赖以往所做过的选择,但决不依赖将来所做的选择,也不依赖子问题的解。
正是由于这种差别,动态规划算法通常以自底向上的方式解决各子问题,贪心算法则通常以自顶向下的方式进行,以迭代的方式做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为规模更小的子问题。

贪心算法的设计步骤

(1)将最优化问题转化为如下形式:做出一次选择后,只剩下一个子问题要求解
(2)证明做出贪心选择后,总能求得原问题最优解,即贪心选择安全
(3)证明做出贪心选择后,子问题具有最优子结构性质。

贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。贪心算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪心算法不要回溯。
同时,要确定一个问题是否适合用贪心算法求解,必须证明每一步所作的贪心选择最终导致问题的整体最优解。证明的大致过程为:首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始,做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明通过每一步做贪心选择,最终可得到问题的整体最优解。

贪心算法的存在问题

(1)不能保证解是最佳的。因为贪心算法总是从局部出发,并没从整体考虑;
(2)贪心算法一般用来解决求最大或最小解;
(3)贪心算法只能确定某些问题的可行性范围。

贪心算法的应用范例

活动安排问题

思路:

所有活动按照结束时间非递减排序,一开始选择活动 1 ,然后依次检查活动 i 是否与当前已选择的所有活动相容。若相容,则将活动i加入到已选择的集合 A 中;否则不选择活动i,继续检查下一活动与集合 A 中活动的相容性

最优装载问题

思路:

采用重量最轻者先装的贪心选择策略,可产生最优装载问题的最优解。

哈夫曼编码

思路:

哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树 T ,算法以 | C | 个叶节点开始,执行 | C | - 1 次的 ” 合并 “ 运算后产生最终所要求的树 T 。设编码字符集中每个字符 c 的频率是 f ( c ) 。以 f 为键值的优先队列 Q 用在做贪心选择时有效确定算法当前要合并的两棵具有最小频率的树。一旦两棵具有最小频率的树合并后,产生一棵新的树,其频率为合并的两棵树的频率之和,并将新树插入优先队列 Q 。

单源最短路径

思路 ( Dijkstra算法 ) :

设置顶点集合 S ,不断地做贪心选择来扩充这个集合。一个顶点属于集合 S 当且仅当从源到该顶点的最短路径长度已知。初始时,S 中仅有源。设 u 是 G 的某一个顶点,把从源到 u 且中间只经过 S 中顶点的路称为从源到 u 的特殊路径,并用数组 dist 记录当前每个顶点所对应的最短特殊路径长度。Dijkstra 算法每次从 V - S 中取出具有最短特殊路径长度的顶点 u ,将 u 添加到 S 中,同时对数组 dist 做必要的修改。一旦 S 包含了所有 V 中顶点,dist 就记录了从源到所有其他顶点之间的最短路径长度。

最小生成树

思路 ( Prim算法 ) :

设 G = ( V , E ) 是连通带权图,V= { 1 , 2 , … , n } 。构造 G 的最小生成树的 Prim 算法基本思想:首先置 S = { 1 } ,然后,只要 S 是 V 的真子集,就做如下贪心选择:选取满足条件 i ∈ S , j ∈ V - S ,且 c [ i ] [ j ] 最小的边 ( c [ i ] [ j ] 表示边 ( i , j ) 的权值 ) ,并将顶点 j 添 加到 S 中。这个过程一直进行到 S = V 为止,选取到的所有边恰好构成 G 的一棵最小生成树。

思路 ( Kruskal算法 ) :

设 G = ( V , E ) 是无向连通带权图,V= { 1 , 2 , … , n } 。构造 G 的最小生成树的 Kruskal 算法基本思想:首先将 G 的 n 个顶点看成 n 个孤立的连通分支,将所有的边按权从小到大排序;然后从第一条边开始,依次权递增的顺序查看每条边,并按下述方法连接两个不同的连通分支:当查看到第 k 条边 ( v , w ) 时,如果端点 v 和 w 分别是当前两个不同的连通分支 T1 和 T2 中的顶点时,就用边 ( v , w ) 将 T1 和 T2 连接成一个连通分支,然后继续查看第 k + 1 条边。这个过程一直进行到只剩下一个连通分支时为止。此时,这个连通分支就是 G 的一棵最小生成树。

多机调度问题

思路:

采用最长处理时间作业优先的贪心选择策略,可以设计出解多机调度问题的较好近似算法。按此策略:
当 n <= m 时,只要将机器 i 的 [ 0 , ti ] 时间区间分配给作业i即可。
当 n > m 时,先将 n 个作业依其所需的处理时间从大到小排序,再依此顺序将作业分配给空闲的机器。

删除问题

思路:

从高位向低位遍历,若当前这一位比它的前一位小,就将它前一位删去,然后继续比较,若当前这一位不比前一位小,就向下遍历,否则继续删。若遍历到最后还能再删,由于当前是一个非递减的序列,因此倒着依次删除是最优的。

会场安排问题

思路:

对所有活动按照开始时间非递减排序。遍历所有活动,首先选第一个进入集合 A ,然后对于活动 i , 若 i 的开始时间比集合 A 的最晚时间要晚,那么就将 i 加入集合A,否则继续看下一个活动是否满足上述条件。遍历结束,集合A中的所有活动都安置在同一会场,然后清空集合 A ( 表示新开一个会场 ) ,再次进行遍历活动,之前安置过的活动不再进入集合 A 。当所有活动都被安置,此时的会场数就是最优解。

区间覆盖问题

思路:

对所有点按照坐标从小到大排序,将第一个点设为区间起点,然后向后枚举,若当前点的距离与区间起点距离小于等于区间长度,就继续枚举,否则将此点设为新的区间起点,然后继续上述过程。若所有点都被覆盖则程序结束。

心急的C小加

思路:

本质是求最少的序列数,满足每个序列内长度跟重量都是非递减的。而当你对所有木棒的长度非递减排序后,就变成了求最小的序列数,满足每个序列内重量是非递减的,这与会场安排问题相似。遍历所有木棒,能放到一个序列里的就放到一个序列里。第一遍过后检查是否有没放置的木棒,若有就继续上述过程,若没有就结束。

多元Huffman编码问题

思路:

如果想使得费用最大,每次合并两堆。先合并费用大的石子会产生更优贡献,类似于哈夫曼编码,每次合并费用最大的两堆石子。
如果想使得费用最小,每次合并 k 堆。先合并费用小的石子会产生更优的贡献,每次合并费用最小的 k 堆石子,如果最后不能恰好合并完,那么第一次合并前,可以添加价值为 0 的石子堆,直到满足每次合并 k 堆最后恰好合并完。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值