算法导论-贪心算法
贪心算法问题解决策略概述

贪心算法问题解决策略概述贪心算法(Greedy Algorithm)是一种简单而有效的问题解决策略,通过每一步的局部最优选择,最终达到全局最优解。
其基本思想是从问题的某个初始解出发,通过贪心的选择,逐步得到一个更优解,以求解整个问题。
本文将对贪心算法的基本原理以及应用领域进行概述。
一、贪心算法的基本原理贪心算法的核心思想是每一步都做出当前的最优选择,将问题分解为一系列子问题,并进行局部最优解的选择,最终得到全局最优解。
二、适用条件贪心算法适用于具有贪心选择性质的问题,即通过局部最优解可以得到全局最优解。
贪心选择性质是指每一步的选择只依赖于当前状态,不受其他步骤的影响。
三、典型应用1. 最小生成树问题:在一个连通图中,找出一个包含所有顶点的边的子集,使得这个子集形成一个树,且所有边的权值之和最小。
2. 哈夫曼编码问题:在编码问题中,通过给频率较高的字符分配较短的编码,从而使得编码的总长度最短。
3. 区间调度问题:给定一组区间,选择尽量多的互不重叠的区间。
4. 零钱支付问题:给定一定面额的硬币和一个要支付的金额,找出支付方式使得所需硬币的数量最少。
5. 背包问题的一些变体:如01背包问题、完全背包问题等。
四、算法步骤贪心算法的思路是通过局部最优解来构建全局最优解。
其一般步骤如下:1. 建立数学模型来描述问题。
2. 将问题分解为若干个子问题。
3. 对每个子问题求解,得到局部最优解。
4. 对所有子问题的局部最优解进行整合,得到原问题的最优解。
五、优缺点贪心算法的优点在于简单、高效,能够快速地找到一个近似最优解。
但是它也有一些缺点,即不能保证能够得到全局最优解,因为贪心策略是基于局部最优的选择,并不能考虑全局情况。
六、总结贪心算法作为一种简单而有效的问题解决策略,在许多实际问题中发挥着重要作用。
通过每一步的局部最优选择,贪心算法能够快速地找到一个近似最优解。
但需要注意的是,贪心算法并不能保证一定能够得到全局最优解,因此在具体应用中需要谨慎分析问题的特点,判断是否适合采用贪心算法。
信息学奥林匹克竞赛指导之基础算法—贪心算法

重量按比例计算。
7
-贪心算法
贪心算法的经典实例
• 思路点拨:本问题是在上一个问题的基础上增加了价值项,所以不能简
单地向上一题那样先选出轻的(轻的可能其价值也小),也不能先拿价
值大的(它可能特别重),而应该综合考虑两个因素。一种直观的贪心
可乘两个人。求用最少的船载所有人的方案。
8
-贪心算法
贪心算法的经典实例
• 思路点拨:考虑最轻的人i,他应该和谁一起乘呢?如果每个人都不能和
他一起乘,则只能每人乘一艘船。否则他应该选择能和他一起乘的人中
最重的一个人j。这样的选择只是让“眼前”的浪费最少,因此它是一种
贪心策略。
• 证明:
• 情况1:i不和任何一个人同乘一艘船,那么可以把j拉过来和他一起乘,总船数不会
法不从整体最优考虑,它所做出的选择只是局部最优解。
3
-贪心算法
贪心算法的概念及其特点
• 贪心算法是从问题的初始状态出发,通过若干次的贪心选择而得
到的最优值的一种求解问题的策略。
• 特点:
• 贪心选择:所谓贪心选择是指应用同一规则,将原问题变为一个相似的
但规模更小的子问题,而后的每一步都是当前看似最佳的选择,且这种
29
-贪心算法
贪心算法的经典应用-3
• 【输出格式】
• 对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数
目的最小值。如果所有喷头都打开还不能浇灌整块草坪,则输出1。
• 【样例输入】
•3
• 8 20 2
•53
30
-贪心算法
贪心算法的经典应用-3
•
•
•
算法导论第4章

12
4.2 贪心算法的基本要素
2、最优子结构性质
当一个问题的最优解包含其子问题的最优解时, 称此问题具有最优子结构性质 称此问题具有最优子结构性质。问题的最优子结构性 最优子结构性质。问题的最优子结构性 质是该问题可用动态规划算法或贪心算法求解的关键 特征。
13
4.2 贪心算法的基本要素
3、贪心算法与动态规划算法的差异
2
顾名思义,贪心算法总是作出在当前看来最好的选择。 也就是说贪心算法并不从整体最优考虑,它所作出的选择 局部最优选择。当然,希望贪心算法 只是在某种意义上的局部最优 只是在某种意义上的局部最优选择。当然,希望贪心算法 得到的最终结果也是整体最优的。虽然贪心算法不能对所 有问题都得到整体最优解,但对许多问题它能产生整体最 优解。如单源最短路经问题,最小生成树问题等。在一些 情况下,即使贪心算法不能得到整体最优解,其最终结果 却是最优解的很好近似。
16
4.2 贪心算法的基本要素
用贪心算法解背包问题的基本步骤:
首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心 首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心 选择策略,将尽可能多的单位重量价值最高 选择策略,将尽可能多的单位重量价值最高的物品装入背包。 单位重量价值最高的物品装入背包。 若将这种物品全部装入背包后,背包内的物品总重量未超过 C,则选择单位重量价值次高的物品并尽可能多地装入背包。 依此策略一直地进行下去,直到背包装满为止。 具体算法可描述如下页:
贪心算法知识点总结

贪心算法知识点总结1. 基本原理贪心算法的基本原理是每一步都选择当前状态下的最优解,以期望最终得到全局最优解。
具体来说,贪心算法通常可以分为以下几个步骤:1)从问题的某个初始解出发2)采用一种迭代的方式,逐步将初始解进行优化3)每一步都是基于当前状态的最优选择来进行优化4)直到无法再进行优化,得到问题的最优解由于贪心算法每一步都要选择局部最优解,因此贪心算法通常具有高效性。
然而,贪心算法并不适用于所有问题,其结果不一定是全局最优解。
因此,在使用贪心算法时需要注意问题的特性和约束条件,以免得到错误的结果。
2. 适用情况贪心算法通常适用于满足以下条件的问题:1)问题的最优解满足“最优子结构”性质:即问题的最优解包含了其子问题的最优解2)问题的求解过程具有“贪心选择性”:即每一步都选择当前状态下的最优解,并不需要考虑未来的后果3)问题的约束条件可以通过局部最优选择满足全局最优解:即问题的解空间中存在一些局部最优解,可以通过一系列的局部最优解构建全局最优解在实际应用中,贪心算法通常用于求解最优化问题,如最小生成树、最短路径、任务调度等问题。
由于贪心算法的高效性,它通常能够在较短的时间内得到较为接近最优解的结果。
然而,贪心算法并不适用于所有问题,对于一些问题,贪心算法将得到错误的结果。
因此,在使用贪心算法时需要谨慎选择问题类型和约束条件,以避免错误的结果。
3. 贪心算法实例在下面的部分,我们将介绍一些常见的贪心算法实例,包括背包问题、活动安排问题、霍夫曼编码等。
3.1 背包问题背包问题是一个经典的优化问题,它包括0-1背包问题、分数背包问题等多种类型。
在0-1背包问题中,给定n种物品和一个容量为C的背包,每种物品i的重量为w[i],价值为v[i],求在不超过背包容量的情况下,如何选择物品放入背包,可以使得背包中的总价值最大。
对于0-1背包问题,贪心算法通常不能得到最优解。
然而,在分数背包问题中,贪心算法通常可以得到近似的最优解。
算法设计与分析 第五章 贪心算法

第五章 贪心算法§1.贪心算法基本思想找零钱 假如售货员需要找给小孩67美分的零钱。
现在,售货员手中只有25美分、10美分、5美分和1美分的硬币。
在小孩的催促下,售货员想尽快将钱找给小孩。
她的做法是:先找不大于67美分的最大硬币25美分硬币,再找不大于67-25=42美分的最大硬币25美分硬币,再找不大于42-25=17美分的最大硬币10美分硬币,再找不大于17-10=7美分的最大硬币5美分硬币,最后售货员再找出两个1美分的硬币。
至此,售货员共找给小孩6枚硬币。
售货员的原则是拿尽可能少的硬币个数找给小孩。
从另一个角度看,如果售货员将捡出的硬币逐一放在手中,最后一起交给小孩,那么售货员想使自己手中的钱数增加的尽量快些,所以每一次都尽可能地捡面额大的硬币。
装载问题 有一艘大船用来装载货物。
假设有n 个货箱,它们的体积相同,重量分别是n w w w ,,21 ,货船的最大载重量是c 。
目标是在船上装最多货箱该怎样装?如果用1=i x 表示装第i 个货箱,而0=i x 表示不装第i 个货箱,则上述问题是解优化问题:求n x x x ,,,21 ,∑=ni i x 1max (5.1.1)c x i ni i ≤∑=1w (5.1.2)贪心方法,顾名思义,是在决策中总是作出在当前看来是最好的选择。
例如找零钱问题中,售货员每捡一个硬币都想着使自己手中的钱尽快达到需要找钱的总数。
在装载问题中,每装一个货箱都想着在不超重的前提下让船装更多的箱子。
但是贪心方法并未考虑整体最优解,它所作出的选择只是在某种意义上的局部最优选择。
当然,在采用贪心算法时未必不希望结果是整体最优的。
事实上,有相当一部分问题,采用贪心算法能够达到整体最优,如前面的找零钱问题以及后面将要讲到的单点源最短路径问题、最小生成树问题、工件排序问题等。
为了更好理解贪心算法,我们将装载问题稍加推广,考虑可分割的背包问题。
背包问题 已知容量为M 的背包和n 件物品。
第三章 贪心算法

2021/2/22
5
如果问题改成:砝码的种类分别为11克、5克和1克, 待称的物体是15克。用贪婪算法应先选一个11克的,然 后选四个1克的,共用五个砝码。这不是最优结果,只 要用三个5克的砝码就够了。
贪婪算法虽不能保证得到最优结果,但对于一些除
了“穷举”方法外没有有效算法的问题,用贪婪算法往
往能很快地得出较好的结果,如果此较好结果与最优结 果相差不是很多的话,此方法还是很实用的。
2021/2/22
9
当n不太大时,适当的取k值,此改进方法常常可以得到 最优解,但不能因此就说一般背包问题有多项式算法。 当n增大时,k不能随着n不断的加大,如k随n增大而同 时加大,其复杂性就是指数型而不是多项式型的了,而 如k取值较小,又不能保证得出最优解。
0021算法笔记——【贪心算法】贪心算法与精彩活动安排问题

0021算法笔记——【贪心算法】贪心算法与活动安排问题1、贪心算法(1)原理:在对问题求解时,总是做出在当前看来是最好的选择。
也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
(2)特性:贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。
能够用贪心算法求解的问题一般具有两个重要特性:贪心选择性质和最优子结构性质。
1)贪心选择性质所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
这是贪心算法可行的第一个基本要素。
贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
证明的大致过程为:首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。
做了贪心选择后,原问题简化为规模更小的类似子问题。
然后用数学归纳法证明通过每一步做贪心选择,最终可得到问题的整体最优解。
其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于利用该问题的最优子结构性质。
2)最优子结构性质当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
(3)贪心算法与动态规划算法的差异:动态规划和贪心算法都是一种递推算法,均有最优子结构性质,通过局部最优解来推导全局最优解。
两者之间的区别在于:贪心算法中作出的每步贪心决策都无法改变,因为贪心策略是由上一步的最优解推导下一步的最优解,而上一部之前的最优解则不作保留,贪心算法每一步的最优解一定包含上一步的最优解。
贪 心 算 法

贪心算法及几个常用的例题贪心算法:一、基本概念:所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。
也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。
贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。
必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。
所以对所采用的贪心策略一定要仔细分析其是否满足无后效性。
二、贪心算法的基本思路:1.建立数学模型来描述问题。
2.把求解的问题分成若干个子问题。
3.对每一子问题求解,得到子问题的局部最优解。
4.把子问题的解局部最优解合成原来解问题的一个解。
三、贪心算法适用的问题贪心策略适用的前提是:局部最优策略能导致产生全局最优解。
实际上,贪心算法适用的情况很少。
一般,对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际数据进行分析,就可做出判断。
四、贪心算法的实现框架从问题的某一初始解出发;while (能朝给定总目标前进一步)利用可行的决策,求出可行解的一个解元素;由所有解元素组合成问题的一个可行解;五、贪心策略的选择因为用贪心算法只能通过解局部最优解的策略来达到全局最优解,因此,一定要注意判断问题是否适合采用贪心算法策略,找到的解是否一定是问题的最优解。
几个经典的例子:一、定义什么是贪心算法呢?所谓贪心算法是指,在对问题求解时,总是做出在当前看来最好的选择。
也就是说,不从整体最优解出发来考虑,它所做出的仅是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题都能产生整体最优解或整体最优解的近似解。
贪心算法的基本思路如下:1. .建立数学模型来描述问题。
2. 把求解的问题分成若干个子问题。
3. 对每个子问题求解,得到每个子问题的局部最优解。
4. 把每个子问题的局部最优解合成为原来问题的一个解。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法导论——贪心算法求解最优化问题的算法通常需要经过一系列的步骤,在每个步骤都面临多种选择。
对于许多最优化问题,使用动态规划算法来求最优解有些杀鸡用牛刀了,可以使用更简单、更高效的算法。
贪心算法(greedy algorithm)就是这样的算法,它在每一步都做出当时看起来最佳的选择。
也就是说,它总是做出局部最优的选择,寄希望这样的选择能导致全局最优解。
本章介绍一些贪心算法能找到最优解的最优化问题。
贪心算法并不保证得到最优解,但对很多问题确实可以求得最优解。
我们首先在16.1节介绍一个简单但非平凡的问题—活动选择问题,这是一个可以用贪心算法求得最优解的问题。
首先考虑用动态规划方法解决这个问题,然后证明一直做出贪心选择就可以得到最优解,从而得到一个贪心算法。
16. 2节会回顾贪心方法的基本要素,并给出一个直接的方法,可用来证明贪心算法的正确性。
16. 3节提出贪心技术的一个重要应用:设计数据压缩编码(Huffman编码)。
在16. 4节中,我们讨论一种称为“拟阵"(matroid)的组合结构的理论基础,贪心算法总是能获得这种结构的最优解。
最后,16. 5节将拟阵应用于单位时间任务调度问题,每个任务均有截止时间和超时惩罚。
贪心方法是一种强有力的算法设计方法,可以很好地解决很多问题。
在后面的章节中,我们会提出很多利用贪心策略设计的算法,包括最小生成树(minimum-spanning-tree)算法(第23章)、单源最短路径的djikstra算法(第24章),以及集合覆盖问题的Chvatal贪心启发式算法(第35章)。
最小生成树算法提供了一个经典的贪心方法的例子。
16.1 贪心选择假如我们无需求解所有子问题就可以选择出一个活动加人到最优解,将会怎样?这将使我们省去递归式(16. 2)中固有的考查所有选择的过程。
实际上,对于活动选择问题,我们只需考虑一个选择:贪心选择。
对于活动选择问题,什么是贪心选择?直观上,我们应该选择这样一个活动,选出它后剩下的资源应能被尽量多的其他任务所用。
现在考虑可选的活动,其中必然有一个最先结束。
因此,直觉告诉我们,应该选择S中最早结束的活动,因为它剩下的资源可供它之后尽量多的活动使用。
(如果S中最早结束的活动有多个,我们可以选择其中任意一个)。
换句话说,由于活动已按结束时间单调递增的顺序排序,贪心选择就是活动a,。
选择最早结束的活动并不是本问题唯一的贪心选择方法,练习16.1-3要求设计其他贪心选择方法。
当做出贪心选择后,只剩下一个子问题需要我们求解:寻找在a,结束后开始的活动。
为什么不需要考虑在a1开始前结束的活动呢?因为s1<f1且f1是最早结束的活动,所以不会有活动的结束时间早s1。
因此,所有与a,兼容的活动都必须在al结束之后开始。
而且,我们已经证明活动选择问题具有最优子结构性质。
令为在ak结束后开始的任务集合。
当我们做出贪心选择,选择了a1后,剩下的S1是唯一需要求解的子问题。
最优子结构性质告诉我们,如果a1在最优解中,那么原问题的最优解由活动a1及子问题S1中所有活动组成。
现在还剩下一个大问题:我们的直觉是正确的吗?贪心选择——最早结束的活动——总是最优解的一部分吗?下面的定理证明了这一点。
定理16. 1考虑任意非空子问题Sk,令am是Sk中结束时间最早的活动则a。
在S*的某个最大兼容活动子集中。
证明 令Ak是Sk的一个最大兼容活动子集,且aj是Ak中结束时间最早的活动。
若aj=am,则已经证明am在Sk的某个最大兼容活动子集中。
若aj不等于am,令集合,即将Ak中的aj替换为am.Ak’中的活动都是不相交的,因为Ak中的活动都是不相交的,aj是Ak中结束时间最早的活动,而fm小于等于fj。
由于,因此得出结论Ak’也是Sk的一个最大兼容活动子集,且它包含am.因此,我们看到虽然可以用动态规划方法求解活动选择问题,但并不需要这样做(此外,我们并未检查活动选择问题是否具有重叠子问题性质)。
相反,我们可以反复选择最早结束的活动,保留与此活动兼容的活动,重复这一过程,直至不再有剩余活动。
而且,因为我们总是选择最早结束的活动,所以选择的活动的结束时间必然是严格递增的。
我们只需按结束时间的单调递增顺序处理所有活动,每个活动只考查一次。
求解活动选择问题的算法不必像基于表格的动态规划算法那样自底向上进行计算。
相反,可以自顶向下进行计算,选择一个活动放人最优解,然后,对剩余的子问题(包含与已选择的活动兼容的活动)进行求解。
贪心算法通常都是这种自顶向下的设计:做出一个选择,然后求解剩下的那个子问题,而不是自底向上地求解出很多子问题,然后再做出选择。
递归贪心算法我们已经看到如何绕过动态规划方法而使用自顶向下的贪心算法来求解活动选择问题,现在我们可以设计一个直接的递归过程来实现贪心算法。
过程RECURSIVE-ACTIVITY-SELECTOR的输人为两个数组s和f,表示活动的开始和结束时间,下标k指出要求解的子问题Sk,以及问题规模n。
它返回凡的一个最大兼容活动集。
我们假定输人的n个活动已经按结束时间的单调递增顺序排列好(公式(16. 1))。
如果未排好序,我们可以在O(n Ign)时间内对它们进行排序,结束时间相同的活动可以任意排列。
为了方便算法初始化,我们添加一个虚拟活动a0,其结束时间f0=0,这样子问题So就是完整的活动集S。
求解原问题即可调用RECURSIVE-ACTIVITY SELECTOR(s, f, 0, n)。
图16-1.显示了算法的执行过程。
在一次递归调用RECURSIVE-ACTIVITY-SELECTOR ( s,f, k, n)的过程中,第2^}3行while循环查找Sk中最早结束的活动。
循环检查ak+1,ak+2,...,an,直至找到第一个与ak兼容的活动am,此活动满足sm>=fk。
如果循环因为查找成功而结束,第5行返回{am}与RECURSIVE-ACTIVITY SELECTOR<s,fm,n)返回的Sm的最大子集的并集。
循环也可能因为m>n而终止,这意味着我们已经检查了Sk中所有活动,未找到与a*兼容者。
在此情况下,,因此第6行返回.假定活动已经按结束时间排好序,则递归调用RECURSIVE-ACTIVITY-SELECTOR(s, f,0, n)的运行时间为O(n),我们稍后证明这个结论。
在整个递归调用过程中,每个活动被且只被第2行的while循环检查一次。
特别地,活动ai在k<i的最后一次调用中被检查。
迭代贪心算法我们可以很容易地将算法转换为迭代形式。
过程RECURSIVE-ACTIVITY SELECTOR几乎就是“尾递归”:它以一个对自身的递归调用再接一次并集操作结尾。
将一个尾递归过程改为迭代形式通常是很直接的,实际上,某些特定语言的编译器可以自动完成这一工作。
如前所述,RECURSIVEACTIVITY-SELECTOR用来求解子问题凡,即由最后完成的任务组成的子问题。
过程GREEDY-ACTIVITY-SELECTOR是过程RECURSIVE ACTIVITY-SELECTOR 的一个迭代版本。
它也假定输人活动已按结束时间单调递增顺序排好序。
它将选出的活动存人集合A中,并将A返回调用者。
过程执行如下。
变量k记录了最近加人集合A的活动的下标,它对应递归算法中的活动ak。
由于我们按结束时间的单调递增顺序处理活动,人总是A中活动的最大结束时间。
也就是说,(16.3)第2~3行选择活动a1,将A的初值设置为只包含此活动,并将k的初值设为此活动的下标。
第4~7行的for循环查找凡中最早结束的活动。
循环依次处理每个活动am,am若与之前选出的活动兼容,则将其加人A,这样选出的am必然是S。
中最早结束的活动。
为了检查活动am是否与A中所有活动都兼容,过程检查公式(16.3)是否成立,即检查活动的开始时间sm 是否不早于最近加人到A中的活动的结束时间fk。
如果活动am是兼容的,第6~7行将其加人A中,并将k设置为m.GREEDY-ACTIVITY-SELECTOR(s,f)返回的集合A与RECURSIVE ACTIVITYSELECTOR(s,f,0,n)返回的集合完全相同。
与递归版本类似,在输人活动已按结束时间排序的前提下,GREEDY-ACTIVITY-SELECTOR的运行时间为O(n).16. 2贪心算法原理贪心算法通过做出一系列选择来求出问题的最优解。
在每个决策点,它做出在当时看来最佳的选择。
这种启发式策略并不保证总能找到最优解,但对有些问题确实有效,如活动选择问题。
本节讨论贪心方法的一些一般性质。
16. l节中设计贪心算法的过程比通常的过程繁琐一些,我们当时经过了如下几个步骤:1.确定问题的最优子结构。
2.设计一个递归算法(对活动选择问题,我们给出了递归式(16.2),但跳过了基于此递归式设计递归算法的步骤)。
3.证明如果我们做出一个贪心选择,则只剩下一个子问题。
4.证明贪心选择总是安全的(步骤3, 4的顺序可以调换)。
5.设计一个递归算法实现贪心策略。
6.将递归算法转换为迭代算法。
在这个过程中,我们详细地看到了贪心算法是如何以动态规划方法为基础的。
例如,在活动选择问题中,我们首先定义了子问题Sij,其中2和7都是可变的。
然后我们发现,如果总是做出贪心选择,则可以将子问题限定为Sk的形式。
与这种繁琐的过程相反,我们可以通过贪心选择来改进最优子结构,使得选择后只留下一个子问题。
在活动选择问题中,我们可以一开始就将第二个下标去掉,将子问题定义为Sk的形式。
然后,我们可以证明,贪心选择(Sk中最早结束的活动am)与剩余兼容活动集的最优解组合在一起,就会得到Sk的最优解。
更一般地,我们可以按如下步骤设计贪心算法:1.将最优化问题转化为这样的形式:对其做出一次选择后,只剩下一个子问题需要求解。
2.证明做出贪心选择后,原问题总是存在最优解,即贪心选择总是安全的。
3.证明做出贪心选择后,剩余的子问题满足性质:其最优解与贪心选择组合即可得到原问题的最优解,这样就得到了最优子结构。
在本章剩余部分中,我们将使用这种更直接的设计方法。
但我们应该知道,在每个贪心算法之下,几乎总有一个更繁琐的动态规划算法。
我们如何证明一个贪心算法是否能求解一个最优化问题呢?并没有适合所有情况的方法,但贪心选择性质和最优子结构是两个关键要素。
如果我们能够证明问题具有这些性质,就向贪心算法迈出了重要一步。
贪心选择性质第一个关键要素是贪心选择性质(greedy choice property):我们可以通过做出局部最优(贪心)选择来构造全局最优解。
换句话说,当进行选择时,我们直接做出在当前问题中看来最优的选择,而不必考虑子问题的解。