Description
假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排。(这个问题实际上是著名的图着色问题。若将每一个活动作为图的一个顶点,不相容活动间用边相连。使相邻顶点着有不同颜色的最小着色数,相应于要找的最小会场数。) 对于给定的k个待安排的活动,计算使用最少会场的时间表。
Input
输入数据的第一行有1 个正整数k(k≤10000),表示有k个待安排的活动。接下来的k行中,每行有2个正整数,分别表示k个待安排的活动开始时间和结束时间。时间以0 点开始的分钟计。
Output
输出一个整数,表示最少会场数。
Sample Input
5
1 23
12 28
25 35
27 80
36 50
Sample Output
3
先转载一手优先队列的做法,确实🐂
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int Maxn=1e4+5;
typedef struct node
{
int Ti_s,Ti_e;
bool operator <(const struct node &a)const
{
if(Ti_e==a.Ti_e)
return Ti_s>a.Ti_s;//s小的在前
return Ti_e>a.Ti_e;//e小的在前
}
} JM;
bool cmp(JM a,JM b)
{
return a.Ti_s<b.Ti_s;
}
int main()
{
int n;
scanf("%d",&n);
priority_queue<JM> q;
JM jm[Maxn];
int i,ans=n;
for(i=0; i<n; i++)
scanf("%d%d",&jm[i].Ti_s,&jm[i].Ti_e);
sort(jm,jm+n,cmp);//先按开始时间从小到大排序;
q.push(jm[0]);
for(i=1; i<n; i++)
{
JM p;
p=q.top();
if(jm[i].Ti_s>=p.Ti_e)
{
q.pop();
ans--;
q.push(jm[i]);
}
else
{
q.push(jm[i]);
}
}
printf("%d\n",ans);
}
//只不过进行模拟的方式变了
//队列中有冲突的节目,可能有上一个安排结束的节目。
//这种方法只影响安排节目的方式,不影响会场数的改变,就比如3 ,1和 2,2都是两个会场。
先将最先开始的节目放入队列,然后开始循环,和后面开始的节目进行比较,
如果开始时间大于前一个的结束时间,那么可以放一个会场,把前一个从队列中移除,并会场所需数-1,再把这个会场压入队列中,这样就可以看成两个会场合并,若是不满足,则该节目需要单独安排会场,此时不能进行会场的合并。
根据贪心的原则,我们一定会先根据开始时间的大小进行排序和安排的,之后这里的优先队列以结束时间为优先级,这里的意思是要追求一场内最多节目,试想,若最早结束的会场节目都不能满足下一个节目的开始时间,那么比这个会场节目结束晚的一定不能满足这个节目的开始时间,也即是说这个节目是要单独进行安排的,若是开始时间早于最晚于已安排的节目的最早结束时间,那么就可以进行会场合并,也无需考虑其他已安排会场的节目是否冲突,如果都没有冲突,那么怎么放置,效果是一样的。
再整一手别的模拟方式。
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct
{
int begin,end;
} TIME;
bool cmp(TIME a,TIME b)
{
return a.begin<b.begin;
}
int main()
{
int i,n,t;
TIME time[10000];
cin>>n;
for(i=0; i<n; i++)
{
cin>>time[i].begin>>time[i].end;
}
sort(time,time+n,cmp);
int ans=0,q=n;
t=0;
while(q>0)
{
ans++;
for(i=0; i<n; i++)
{
if(time[i].end!=-1&&t<=time[i].begin)
{
t=time[i].end;
time[i].end=-1;
q--;
}
}
t=0;
}
cout<<ans<<endl;
return 0;
}