题意:
农场主约翰发现他的奶牛剧烈运动后产奶的质量更高,所以他决定让N头(1 <= N <= 25,000)奶牛去附近爬山再返回来。
第i头奶牛用时U(i)爬上山,用时D(i)下山。作为家畜,奶牛们每段路都要有农夫的帮助,可是由于经济疲软,农场里只有两个农夫John和Don。John计划引导奶牛爬山,Don引导奶牛下山。虽然每个奶牛都需要向导,但每段旅途只有一名农夫。所有任何时刻只有一头奶牛爬山也只能有一头奶牛下山,奶牛爬上山后,可以暂时停留在山顶上等待Don的帮助。奶牛上山的顺序和下山的顺序不一定要相同。
请计算出所有N 头牛完成旅程的最短时间
分析:
上山必定是连续不断的,最优的情况就是下山也尽量保持连续不断,
于是我们就有了一个目标:让在山顶等待的牛多一些,让下山序列尽量连续,同时让第一次下山时间尽可能接近第一次上山时间。
我们要让山上的牛多一点,即让上山快的牛先上来,但是要注意可能下山太快,山上都还没有牛就下山了,会出现等待。所以我们可以按照上山时间和下山时间分别考虑(这里记上山时间为 up ,下山时间为 dn )
当 up < dn ,按 up 升序排序
当 up ≥ dn ,按 dn 降序排序
code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
//当 up<dn ,按 up 升序排序
//当 up≥dn ,按 dn 降序排序
struct Node{
int up , down ;
bool operator < (Node no1) const{
if(up<down){
if(no1.up < no1.down) return up < no1.up ;//内部排序
else return true;
}else{
if(no1.up < no1.down) return false;
else return down > no1.down;//内部排序
}
}
};
Node a[200005] ;
int n ;
signed main()
{
//freopen("in","r",stdin);
scanf("%lld",&n);
for(int i = 1 ; i <= n ; i++) {
scanf("%lld%lld",&a[i].up,&a[i].down);
}
sort(a+1,a+1+n);
for(int i = 1 ; i <= n ; i++) {
a[i].up += a[i-1].up;
}
for(int i = 1 ; i <= n ; i++) {
//该牛的下山时间取决于max(当前牛到达时间,上一个牛完成下山时间)
a[i].down += max(a[i].up,a[i-1].down);
}
cout << a[n].down << endl;
return 0 ;
}