设有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相容。
使用贪心算法提供了一个简单漂亮的方法使得尽可能多的活动能兼容地使用公共资源。
例:设待安排的11个活动的开始时间和结束时间如下表所示,按结束时间的非减序排列。
算法分析:
对输入的活动按其完成时间进行非减序排列,总是选择最早完成时间的相容活动加入到安排中。该算法的贪心选择的意义是使剩余的可安排时间段极大化,以便安排尽可能多的活动。
下面是C语言实现(DEV c++4.9.9.2运行通过)
#include<stdio.h>
void greedy(int s[],int f[],int a[],int k);
int main()
{
int s[] = {1,3,0,5,3,5,6,8,8,2,12};
int f[] = {4,5,6,7,8,9,10,11,12,13,14};
int k;
k = sizeof(f)/sizeof(f[0]);
int *a;
a = (int*)malloc(sizeof(int)*k);
greedy(s,f,a,k);
system("PAUSE");
}
/*
* s[]:活动的开始时间
* f[]:活动的结束时间(非降序排列)
* a[]:0或者1,为0表示活动不被安排,1表示活动被安排
* k:活动个数
*/
void greedy(int s[],int f[],int a[],int k)
{
int i;
int j = 0;
for(i=0;i<k;i++)
{
a[i] = 0;//初始所有活动都未被安排
}
a[0] = 1;
printf("第1个活动被安排\n");
int count = 1;
for(i=1;i<k;i++)
{
if(s[i] > f[j])
{
a[i] = 1;
printf("开始%d,结束%d.",s[i],f[i]);
j = i;
count++;
printf("第%d个活动被安排\n",i+1);
}
}
printf("总计%d个活动被安排\n",count);
}
对于活动安排问题,贪心算法总是能求得整体的最优解。
有兴趣的朋友们可以用数学归纳法证明。