USACO 二道工序
Description
每天早晨,约翰的 N 头奶牛都要排队接受挤奶。为了提高效率,约翰把挤奶过程分成了两道工 序。约翰负责第一道工序,第二道工序则让他的好友罗伯帮忙。奶牛们进入牛棚后,首先在约翰处排 队,依次接受第一道工序,完成后再去罗伯处排队,接受第二道工序。挤奶过程中没有奶牛插队或者 开小差,约翰和罗伯是工作狂,中途不会休息,直到挤完所有奶牛的牛奶。
约翰发现,如果奶牛的排队顺序不加规划,可能会浪费很多时间。比如一些奶牛的第一道工序很 长,那么罗伯就会有很长一段时间无事可做。请你帮助约翰计算一下,应该让奶牛按照什么样的规律 排队,才能最节约时间。
Input Format
• 第一行:单个整数 N ,1 ≤ N ≤ 25000
• 第二行到第 N + 1 行:第 i + 1 行有两个整数 Ai 和 Bi,分别表示第 i 头奶牛接受第一道工序 和第二道工序所需要的时间,1 ≤ Ai,Bi ≤ 2000
Output Format
单个整数:表示最少需要多少时间才能挤完所有奶牛的牛奶
Sample Input
3 2 2 7 4 3 5
Sample Output
16 解释 排队顺序应该是第三头,第一头,第二头
solution
对于两头牛a,b;
满足下面条件时a应该在b之前:
max(A1+B1+B2, A1+A2+B2)<=max(A2+B2+B1, A2+A1+B1)
化简:
max(A2, B1)+A1+B2<=max(A1, B2)+A2+B1
max(A2, B1)-A2-B1<=max(A1, B2)-A1-B2
-min(A2, B1)<=-min(A1, B2)
min(A1, B2)<=min(A2, B1)
一道比较好的局部调整法贪心题
#include<cstdio> #include<algorithm> inline int min(int a,int b){a-=b;return b+(a&(a>>31));} inline int max(int a,int b){a-=b;return b+(a&(~a>>31));} int N,T1,T2; struct info{int A,B;}cow[25012]; bool cmp(info x,info y){return min(x.A,y.B)<min(x.B,y.A);} int main() { scanf("%d", &N); for(int g=1;g<=N;++g) scanf("%d%d", &cow[g].A,&cow[g].B); std::sort(cow+1,cow+N+1,cmp); for(int g=1;g<=N;++g) { if(T1>T2) T2=T1; T1+=cow[g].A; T2=max(T1,T2)+cow[g].B; } printf("%d", T2); return 0; }