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;
}
 
原文地址:https://www.cnblogs.com/HollowM/p/7795151.html