贪心算法之活动安排问题

一、贪心算法

顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。

二、例题

活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子。该问题要求高效地安排一系列争用某一公共资源的活动。贪心算法提供了一个简单、漂亮的方法使得尽可能多的活动能兼容地使用公共资源。

三、分析

设有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相容。

下面给出的解活动安排问题的算法GreedySelector中,各活动的起始时间和结束时间分别存储在数组s和f中,且按结束时间升序排序,即 f1≤f2≤f3≤......≤fn。如果所给出的活动集合未按此序排序,可以用O(nlogn)的时间重排。

template<class Type>

void GreedySelector(int n, Type s[], Type f[], bool A[]){

A[1]=true;

int j=1;

for (int i=2;i<=n;i++) {

    if (s[i]>=f[j]) { A[i]=true; j=i;

    } else

    A[i]=false;

}

用集合A存储所选择的活动,如果活动i被选了,则A[i]为true,变量j用于记录最近一次加入到A中(也就是被选了)的活动。

由于输入的活动以其结束时间升序排列,所以算法greedySelector每次总是选择具有最早结束时间的相容活动加入集合A中。直观上,按这种方法选择相容活动为未安排活动留下尽可能多的时间。也就是说,该算法的贪心选择的意义是使剩余的可安排时间段极大化, 以便安排尽可能多的相容活动。

算法greedySelector的效率极高。当输入的活动已按结束时间的非减序排列,算法只需O(n)的时间安排n个活动,使最多的活动能相容地使用公共资源。

猜你喜欢

转载自blog.csdn.net/qq_32919451/article/details/81194311