贪心算法基础之活动时间安排(二) 51nod 贪心教程

来源:互联网 发布:百度地图lbs数据 编辑:程序博客网 时间:2024/06/05 22:35

有若干个活动,第i个开始时间和结束时间是[Si,fi),活动之间不能交叠,要把活动都安排完,至少需要几个教室?

输入

第一行一个正整数n (n <= 10000)代表活动的个数。第二行到第(n + 1)行包含n个开始时间和结束时间。开始时间严格小于结束时间,并且时间都是非负整数,小于1000000000

输出

一行包含一个整数表示最少教室的个数。

输入示例

31 23 42 9

输出示例

2


解题思路一:


把所有的开始时间和结束时间按从小到大排序,


然后我们从最小的时间开始走,


遇到的开始时间就加一个会场,遇到结束时间就建一个会场。


一开始是0个会场,走到最后也一定是0个(开始时间和结束时间的数目相等)


那么在时间走的过程中,一定会经历会场数很多的状态,我们需要记录下最大的会场数,即答案


代码:

#include<stdio.h>#include<algorithm>using namespace std;int main(){int a[10000];//开始时间int b[10000];//结束时间int n,i,j;while(scanf("%d",&n)!=EOF){for(int i=0;i<n;i++)scanf("%d%d",&a[i],&b[i]);sort(a,a+n);sort(b,b+n);i=j=0;int count=0;//实时会场数int ans=0;//答案 while(i<n&&j<n)//a,b两个数组同时在时间轴上走 {if(a[i]<b[j]){count++;i++;}if(ans<count)//这句对ans的更新一定要紧跟在count加了之后 ans=count;if(a[i]>b[j]){count--;j++;}if(a[i]==b[j]){i++;j++;}}//时间轴走完了开始时间或者结束时间,就可以得到最多的同时进行的活动的场数 printf("%d\n",ans);}return 0;}






解题思路二:

建立一个时间轴,(像一维数轴一样即可),如图




把所有活动安排的时间段以线段的形式画在时间轴上,


某一时刻需要的教室数,其实就是那一刻的线段重合的数目。


所以,我们只要找出最多能重合多少线段。


代码:

#include<stdio.h>#include<stdlib.h>#include<algorithm>#include<queue>#include<vector>using namespace std;struct node{int b,e;}a[100100];bool cmp(node a,node b){return a.b<b.b;} int main(){int N;while(~scanf("%d",&N)){priority_queue<int, vector<int>, greater<int> > q; //优先队列先出小的元素 for(int i=0;i<N;i++){scanf("%d%d",&a[i].b,&a[i].e);}sort(a,a+N,cmp);//按开始时间从小到大排序。 q.push(a[0].e);//队列装已经进行了的活动的结束时间 int count =0;//记录下会场最多的数目 for(int i=1;i<N;i++){while(!q.empty()&&q.top()<=a[i].b)//时间点过了的活动从队列里删除 q.pop();q.push(a[i].e);if(count<q.size())count=q.size();}printf("%d\n",count);}return 0;}




解题思路一:

建立一个时间轴,(像一维数轴一样即可),把所有的活动时间按结束时间排序,


以线段的形式画在时间轴上,然后遍历所有活动。每加入一个活动,只需满足上一个占用着会场的活动结束了。


为什么要以结束时间排序呢?因为我们要尽量多的安排活动,当然希望下一个进来的活动能够成功安排进去,


那么就要求上一个活动尽量早结束。






0 0
原创粉丝点击