性质
贪心选择性质
整体最优可通过一系列的局部最优选择,即贪心选择来达到。也就是说贪心选择是当前状态下做出的最好选择。
如何证明贪心选择是当前状态下做出的最好选择。如果可以证明存在整体的最优解包含第一步的贪心选择,那么贪心选择是当前状态下做出的最好选择。通常采用反证法证明。
使用贪心算法前一般需要“排序”数据,选择如何对数据进行排序是求解问题的关键之一。
最优子结构
一个问题的最优解包含其子结构的最优解,则称此问题具有最优子结构性质。
子问题有两种理解方式。
- 经过贪心选择过后剩下的子问题
- 经过k-1步贪心选择过后,载经第k步,得到的解,依然是子问题的最优解。
典例
时间安排问题
- 问题:有n个活动,知道每个活动开始时间bi, 结束时间ei, 求一种最优活动安排方案,使得所有安排的活动个数最多。
问题求解:
- 排序,按结束时间ei递增排序,得到S[1…n]
- 局部:用flag[1…i] 记录从1到 i 的任务是否得到安排,用preend记录上一个被安排任务的结束时间
- 贪心选择策略:S[i].start >= preend, 则安排第i个任务,否则不安排。
证明:
- 首先证明总存在一个以活动1开始的最优解。
如果第一个选中的活动为k(k≠1),可以构造另一个最优解Y,Y中的活动是兼容的,Y与X的活动数相同。
那么用活动1取代活动k得到Y’,因为e1≤ek,所以Y’中的活动是兼容的,即Y’也是最优的,这就说明总存在一个以活动1开始的最优解。 - 当做出了对活动1的贪心选择后,原问题就变成了在活动2、…、n中找与活动1兼容的那些活动的子问题。亦即,如果X为原问题的一个最优解,则X’=X-{1}也是活动选择问题A’={i∈A | bi≥e1}的一个最优解。
反证法:如果能找到一个A’的含有比X’更多活动的解Y’,则将活动1加入Y’后就得到A的一个包含比X更多活动的解Y,这就与X是最优解的假设相矛盾。
因此,在每一次贪心选择后,留下的是一个与原问题具有相同形式的最优化问题,即最优子结构性质。
多机调度问题
- 问题:有n个独立的作业和m个相同的机器,
问题求解:
- 排序,按作业时间递减排序, 得到S[1…n]
- 局部:f(i)表示对S[1…i]这i个作业进行多机调度
- 贪心选择策略:长作业优先
Kruskal 算法求最小生成树
证明:
(1)k=1时,首先T中没有任何边,设e1是G中权最小的边,加入e1不会产生任何回路。显然是正确的。
(2)假设算法进行了k-1步产生k-1条边,即e1,e2,…,ek-1,对应的边集合为TE1,产生的T1=(V1,TE1)是最小生成树T的子树(V1为TE1中的顶点集)。
(3)算法第k步选择了边e=(v,u),设TE2= TE1∪{e},TE2中的边把G中顶点分成两个或者两个以上的连通分量。
设S1是添加边e后包含顶点v的连通分量的顶点集,S2是添加边e后包含顶点u的连通分量的顶点集。
显然e是离开S的最短边之一(因为之前所有较短边都已经考察过,它们或者添加到T中,或者因为在同一个连通分量中而被丢弃)。
现要证明T2=(V2,TE2)也是最小生成树的子树(V2为TE2中的顶点集)。
若最终的最小生成树T包含e=(v,u),那么就不需要再进一步证明了。否则在T中S1和S2之间一定存在一条边e’=(x,y)(在后面添加的),现在再在S1和S2之间添加边e得必构成一个回路,如下图所示:
显然e’的权值大于或等于e的权值即cost(e’)≥cost(e),否则边e’应该在前面添加,这样由S1和S2加上e1构成的生成树的权值和大于等于T2的权值和,说明T不是最小生成树,与T是最小生成树的假设矛盾,从而证明T2是最小生成树的子树。