[CF] Final Exam Arrangement
问题大意:
就是有1--N们课程,每一个课程都有一个考试区间[s,t),左闭右开,没有时间重叠的课程不能安排在一起,让尽量多的课程安排在一起,最少能安排多少天,并输出先后的课程:
题目分析:
贪心算法的综合运用,关键看怎么贪心,求重叠部分最多的,这个题不同于一般的贪心。我的做法是首先定义一个结构体里面包括课程序号、开始区间S、结束区间t,以及安排天数;第一个排序就是按照开始区间由小到大(如果开始区间相同就是结束区间由小到大);接下来注意啦!!!!!!就是天数的计算了,首先第一个天数是一,接下来判断下一个科目的开始区间是否小于上一科目的结束区间,若果是这两个科目就在同一天(这个时候不要以为就完事了,还要把这上下科目开始区间的大的跟结束区间小的赋值给下一个区间,不然就会输出错误,我第一次提交这点就错了);如果不小于的话,下一科目的天数就要比上一科目的天数加一;这个时候你的代码算是完成的差不多了;接下来就要再次排一次序了,按照天数由小到大排(如果天数相同就按科目由小到大排);这一步完了就是输出了,这就是你看题目输出要求就可以了!哎呦!终于写完了!
AC代码:
#include<stdio.h> #include<algorithm> using namespace std; const int maxn=100005; struct ST { int s; int t; int num; int day; }c[maxn]; bool cmp1(ST a,ST b) { if(a.s==b.s) return a.t<b.t; else return a.s<b.s; } bool cmp2(ST a,ST b) { if(a.day==b.day) return a.num<b.num; else return a.day<b.day; } int main() { int n,i; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) { scanf("%d%d",&c[i].s,&c[i].t); c[i].num=i; c[i].day=0; } sort(c+1,c+n+1,cmp1); c[1].day=1; for(i=2;i<=n;i++) { if(c[i].s<c[i-1].t) { c[i].day=c[i-1].day; c[i].s = max(c[i].s, c[i-1].s); c[i].t = min(c[i].t, c[i-1].t); } else c[i].day=c[i-1].day+1; } sort(c+1,c+n+1,cmp2); printf("%d\n",c[n].day); printf("%d",c[1].num); for(i=2;i<=n;i++) { if(c[i].day==c[i-1].day) printf(" %d",c[i].num); else printf("\n%d",c[i].num); } printf("\n"); } return 0; }