问题描述:
假设有一个需要使用某一资源的由n个活动所组成的集合S,S=(1,…,n)。该资源在任何时刻只能被一个活动所占用,活动i有一个开始时间bi和结束时间ei(bi<ei),其执行时间为ei-bi,假设最早活动执行时间为0。一旦某个活动开始执行,就不能被打断,直到其执行完毕。若活动i和活动j有bi≥ej或bj≥ei,则称这两个活动兼容。设计一种最优活动安排方案,使得所有安排的活动个数最多。
问题求解:
采用贪心算法的策略是每一步总是选择这样一个活动来占用资源,它能够使得余下的未调度的时间最大化,使得兼容的活动尽可能多。为此先按活动结束时间递增排序,再从头开始依次选择兼容活动(用B集合表示),从而得到最大兼容活动子集(包含兼容活动个数最多的子集)。由于活动按结束时间递增排序,每次总是选择具有最早完成的兼容活动加入集合B中,所以选择的兼容活动为未安排的活动留下尽可能多的时间,也就是使得剩余的可安排时间段极大化,以便安排尽可能多的兼容活动。
#include<iostream>
#include<string.h>
#include<algorithm>
#define MAXN 51
using namespace std;
int n=11;//表示11个活动待安排
struct Action{
int b;//活动开始时间
int e;//活动结束时间
bool operator < (const Action &s)const{
return e<=s.e;
}
};
Action A[]={{0},{1,4},{3,5},{0,6},{5,7},{3,8},{5,9},{6,10},{8,11},{8,12},{2,13},{12,15}};
int flag[MAXN];//记录选择的活动
int Count=0;//记录选取活动个数
void solve();
void output();
int main()
{
solve();
output();
return 0;
}
void solve()
{
int i;
int preend=0;
for(i=1;i<=n;i++){
if(A[i].b>=preend){
flag[i]=true;
preend=A[i].e;
}
}
}
void output()
{
int i;
cout<<"求解结果:\n";
cout<<"选取的活动:";
for(i=1;i<=n;i++){
if(flag[i]==1){
cout<<"["<<A[i].b<<','<<A[i].e<<']'<<' ';
Count++;
}
}
cout<<'\n'<<"共选取了"<<Count<<"个活动"<<endl;
}
#include<iostream>
#include<string.h>
#define MAXN 51
using namespace std;
int n=11;//表示11个活动待安排
int b[]={0,1,3,0,5,3,5,6,8,8,2,12};
int e[]={0,4,5,6,7,8,9,10,11,12,13,15};
int cnt=0;
int B[MAXN];
int E[MAXN];
void solve();
void output();
int main()
{
memset(B,0,sizeof(B));
memset(E,0,sizeof(E));
solve();
output();
return 0;
}
void solve()
{
int i,j=0;
B[0]=b[0];
E[0]=e[0];
for(i=1;i<=n;i++){
if(b[i]>=e[j]){
j=i;
cnt++;
B[cnt]=b[j];
E[cnt]=e[j];
}
}
}
void output()
{
int i;
cout<<"求解结果为:"<<endl;
cout<<"选取的活动为:";
for(i=1;i<=cnt;i++){
cout<<'['<<B[i]<<','<<E[i]<<']'<<' ';
}
cout<<"\n共选取"<<cnt<<"个活动"<<endl;
}