题目链接: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\n",ans*n); 60 } 61 return 0; 62 }
原文地址:https://www.cnblogs.com/zjl192628928/p/9407987.html