顾名思义,贪心算法总是做出当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所做的选择只是在某种意义上的局部最优选择。
当然,希望贪心算法得到的最终结果也是整体最优解。
虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。
在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的整体近似。
贪心算法的一般框架:
•GreedyAlgorithm(parameters)
•{
•初始化;
•重复执行以下的操作:
• 选择当前可以选择的最优解;
• 将当前所选择的局部最优解加入到问题的全局解(局部最优解是全局解的一部分)中去;
•直至满足问题求解的结束条件。
•}
活动安排问题:
活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子。
该问题要求高效地安排一系列争用某一公共资源的活动。
贪心算法使得尽可能多的活动能兼容(多个活动使用资源的时间不冲突)地使用公共资源。
设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。
每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi, 且si <fi 。
如果选择了活动i,则它在[si, fi)内占用资源。
若[si, fi)与[sj, fj)不相交,则称活动i与j是相容的。即当si≥fj或sj≥fi时,活动i与活动j相容。
活动安排问题就是求E的最大相容活动子集。
输入:活动的数目n,各个活动的开始时间与结束时间
输出:各个活动是否安排,安排的话输出1,反之输出0.
运行结果:
用数组s,f,A分别存放所有活动的起始时间,结束时间以及是否予以安排的标记。
某项活动结束时间愈早,安排其他活动的剩余区间愈大,所以贪心策略为尽量选择结束时间早的活动来安排
为此,将数组中的活动按结束时间的非减顺序排序,即f1 <= f2 <= ... fn
显然排序需要的时间为O(nlogn).
template <class Type>
void GreedySelector(int n, Type *s, Type *f, bool *A)
{
int i, j;
A[1] = true;
j = 1;
for(i = 2; i <= n; i++)
{
if(s[i] >= f[j])
{
A[i] = true;
j = i;
}
else
A[i] = false;
}
}
由于输入的活动以其完成时间的非减序排列,所以算法greedySelector每次总是选择具有最早完成时间的相容活动加入集合A中。
算法贪心选择的意义是使剩余的可安排时间段极大化,以便安排尽可能多的相容活动。
当输入的活动已按结束时间的非减序排列,算法只需O(n)的时间安排n个活动,使最多的活动能相容地使用公共资源。
如果所给出的活动未按非减序排列,可以用O(nlogn)的时间重排。
若被检查的活动i的开始时间si小于最近选择的活动j的结束时间fi,则不选择活动i,否则选择活动i加入集合A中。
贪心算法并不总能求得问题的整体最优解。但对于活动安排问题,greedySelector却总能求得的整体最优解,即它最终所确定的相容活动集合A的规模最大。这个结论可以用数学归纳法证明。
贪心算法也能获得最优解:
n设活动集合E={1, 2, …, n}已经按结束时间的非减顺序排列,活动1具有最早结束时间。
n首先,必定有一个最优解包含活动1。
不然设AÍE是最优解且A中最早结束的活动是k。若k = 1,则最优解包含活动1。若k>1,则活动1必与A中除k以外的活动相容。令B=(A–{k})∪{1},则B也是一个最优解。
n其次,若A是原问题的包含活动1的最优解,则A¢=A – {1}是活动集合E¢={i∈E:si≥f1}的一个最优解。
不然设B¢是E¢的解且|B¢|>|A¢|,则B¢∪{1}是E的解且|B¢| + 1>|A|。此与A是最优解矛盾。
n对贪心选择次数用数学归纳法即知,贪心算法最终产生原问题的最优解。
贪心算法的基本要素:
从许多用贪心算法求解的问题中看到,这类问题一般具有2个重要性质:贪心选择性质和最优子结构性质
贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择(即贪心选择)来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
动态规划算法通常以自底向上的方式解各子问题
贪心算法则通常以自顶向下的方式进行,以迭代方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
对具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征.
结论:
1.问题能用动态规划法解的不一定能用贪心算法解;
2.反之能用贪心法一定能用动态规划法,但是,贪心算法的效率一般高于动态规划法,因而还是应用贪心算法。