题目链接:http://codeforces.com/problemset/problem/589/F
题目大意:一位美食家进入宴会厅,厨师为客人提供了n道菜。美食家知道时间表:每个菜肴都将供应。
对于第i道菜肴,他知道时间ai和bi的两个整数时刻(从宴会开始的几秒钟内) - ai为该菜端出来的时间,bi为该菜端走的时间(ai <BI)。例如,如果ai = 10且bi = 11,那么第i个菜肴可在一秒钟内进食。
菜肴数量非常大,所以只要菜肴可以吃(即,在大厅里),它就无法用完。
美食家想要尝试每道菜,不要冒犯任何厨师。因此,美食家想要在相同的时间内吃每道菜。在吃饭期间,美食可以在菜肴之间立即切换。仅在整数时刻允许在菜肴之间切换。
美食家希望在宴会上尽可能长时间吃饭而不违反上述任何条件。你能帮助他,并找出他在宴会上吃的最长时间吗?
输入
第一行输入包含一个整数n(1≤n≤100) - 宴会上的菜肴数量。
以下n行包含有关菜肴可用性的信息。第i行包含两个整数ai和bi(0≤ai<bi≤10000) - 第i个菜肴可用于进食以及第i个菜肴从大厅被带走时的时刻。
产量
输出应该包含唯一的整数 - 美食家可以在宴会上吃的最大总时间。
美食可以在菜肴之间即时切换,但只能在整个时间点切换。在吃完任何其他菜肴后,它可以返回菜肴。此外,在每个时刻,他都可以吃不超过一道菜。
例:
输入:
3
2 4
1 5
6 9
输出
6
解题思路:这个题目有点像区间调度问题,都是按结束时间最早的来排。被拿走时间最早的菜是最需要先吃的,因为先吃收盘早的菜对后面的菜影响就小。若收盘时间相同,那就按上菜时间来排,先吃上菜早的。然后我们就二分吃菜的时间,判断是否每道菜都可以吃达到该时间。
然后剩下的问题就是怎么判断每道菜吃的时间都可以达到t了,就是直接遍历每道菜的开始时间到结尾时间,定义一个vis数组,在x秒吃了该菜则把vis[x]标为1,下次该时刻就不吃其他的菜了。
附上代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 int n,ans,vis[10005];
7 struct node{
8 int a,b;
9 bool operator<(const node &x)const
10 {
11 if(b!=x.b) return b<x.b; //按收盘时间从早到晚排
12 return a<x.a;
13 }
14 }st[105];
15 bool judge(int t)
16 {
17 memset(vis,0,sizeof(vis));
18 for(int i=0;i<n;i++)
19 {
20 int cnt=0; //记录第i到菜吃的时间
21 for(int j=st[i].a;j<st[i].b;j++)
22 {
23 if(!vis[j])
24 {
25 vis[j]=1; //j秒时吃了第i到菜
26 cnt++;
27 if(cnt==t) break;
28 }
29 }
30 if(cnt<t) return false; //第i到菜不能达到时间t,
31 }
32 return true;
33 }
34 void binary_search()
35 {
36 int low=0,high=10000;
37 while(low<=high)
38 {
39 int mid=(low+high)/2;
40 if(judge(mid))
41 {
42 ans=mid;
43 low=mid+1;
44 }
45 else
46 high=mid-1;
47 }
48 return;
49 }
50 int main()
51 {
52 while(scanf("%d",&n)!=EOF)
53 {
54 ans=0;
55 for(int i=0;i<n;i++)
56 scanf("%d%d",&st[i].a,&st[i].b);
57 sort(st,st+n);
58 binary_search();
59 printf("%d
",ans*n);
60 }
61 return 0;
62 }