[做得多了就水了]事件选择
【描述】
Dragon开了一个新的律师事务所,他每天需要处理很多的事情:每一个顾客要求Dragon在某一段固定的时间内为其提供咨询服务。具体的说,第i名顾客需要Dragon在时间[ai, bi]中为其服务。假如Dragon同学答应为顾客i提供咨询,那么在时间[ai, bi]中,Dragon同学就不能再为第二名顾客提供服务,但是在对顾客i的服务结束后可以立刻可对下一名顾客服务,就是说在服务顾客([1..3])后可直接服务([3..4])。现在Dragon同学希望能给最多的顾客提供服务。
我们认为初始时刻为0。
【输入格式】
第一行一个正整数n,表示顾客总数。然后n行每行两个正整数a[i]、b[i],描述第i名顾客的要求。
【输出格式】
一行一个正整数表示最多能服务的顾客。
【样例输入】
3
1 3
2 4
3 5
【样例输出】
2
【数据范围】
0 <= a[i] < b[i] <= 100000;
0 < n < 100000。
【分析】
这是经典的叫什么任务分配的动归。f[i]表示i时刻能得到的最多的人数。从后向前f[i]=max(f[i-1],f[c[p].end]+1),其中c[p].str等于i。
//100% #include <stdio.h> #include <stdlib.h> #define maxn 100010 int f[maxn]; struct ss { int str,end; } c[maxn]; int n,p; int cmp(const void*a,const void*b) { ss c=*(ss*)a,d=*(ss*)b; if (c.str<d.str) return -1; return 1; } int main() { freopen("affair.in","r",stdin); freopen("affair.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d%d",&c[i].str,&c[i].end); c[0].str=-1; qsort(c,n+1,sizeof(ss),cmp); p=n; for (int i=c[n].str;i>=0;--i) { f[i]=f[i+1]; while (c[p].str>i) --p; if (c[p].str==i) while (c[p].str==i) { if (f[c[p].end]+1>f[i]) f[i]=f[c[p].end]+1; --p; } } printf("%d\n",f[0]); return 0; }