1.题目描述:活动安排问题
设有n个活动集合E= {1,2,...,n},其中每个活动都要求使用同一资源,而在同一时间内只有一个活动能使用这一资源;
每个活动 i 都有一个要求使用该资源的起始时间 Si 和一个结束时间 fi,且 si < f i。如果选择了活动 i ,则它在半开时间区间 [si ,fi)内占用资源;
若区间 [si,fi) 与区间[sj,fj) 不相交,则称活动 i 与活动 j 是相容的。即当 si >= fj 或sj >= fi 时,活动 i 与 活动 j 相容;
活动安排问题就是要在所给的活动结合中选出最大的相容活动子集和
2.分析:——使用贪心算法实现
该问题即要求高效的安排一系列争用某一公共资源的活动。
3.贪心算法:
贪心策略:根据给的活动开始时间和结束时间,活动安排至少有三种看似合理的贪心策略可 供选择。
(1)每次从剩下未安排的活动中选择具有最早开始时间且不会与已安排的活动重叠的活动来安排,这样可以增大资源的利用率。
(2)每次从剩下未安排的活动中选择使用时间最短且不会与已安排的活动重叠的活动来安排。
(3)每次从剩下未安排的活动中选择最早结束时间且不会与已安排的活动重叠活动来安排。
通过比较上面三种策略,我们知道应该选用第三种,因为根据“活动结束时间=活动开始时间+使用资源时间”
根据问题描述和所选用的贪心策略,对贪心策略求解活动安排的GreedySelector算法设计思路如下:
(1)初始化。将k个活动的开始时间存储在数组S中;将k个活动的结束时间存储在数组F中且按照结束时间的非减序:f1≤f2≤…≤fn,数组S需要做相应的调整;采用集合A来存储问题的解,即所选择的活动集合,活动i如果在集合A中,当且仅当A[i]=ture.
(2)根据贪心策略,算法GreedySelector首先选择活动1,即令A[1]=true.
(3)依次扫描每一个活动,如果活动i的开始时间不小于最后一个选入集合A中的活动结束时间,即活动i和A中活动相同,则将活动i加入集合A中;否则,放弃活动i,继续检查下一个活动与集合A中活动相容性。
4.代码实现:
#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);
}