题解 P1561 【[USACO12JAN]爬山Mountain Climbing】

· · 题解

被叫去给学弟讲这道题,没想到被学弟Hack了。。。Orz

做法和大家一样:

ans=\max\left\{\sum_{k=1}^n{up_k}+down_{\min},\sum_{k=1}^n{down_k}+up_{\min}\right\}

但是这个做法是不完全正确的,比如以下数据:

3
6 4
8 3
2 1

正确答案应该是18而不是17,这个可以手动模拟,会发现之前的做法有问题。

我去查了一下USACO官方题解,下面来简单说一下。

代码:

#include <cstdio>
#include <algorithm>

using std::sort;
using std::max;

const int MAXN=25005;
int n;
int up_tm[MAXN],dwn_tm[MAXN];

struct Cow{
    int up,dwn;
    static bool cmp_tm(const Cow &a,const Cow &b){
        if(a.up<a.dwn){
            if(b.up<b.dwn) return a.up<b.up;
            else return true;
        }
        else{
            if(b.up<b.dwn) return false;
            else return a.dwn>b.dwn;
        }
    }
}cow[MAXN];

inline int greedy(){
    sort(cow+1,cow+n+1,Cow::cmp_tm);
    for(int i=1;i<=n;++i)
        up_tm[i]=up_tm[i-1]+cow[i].up;
    for(int i=1;i<=n;++i)
        dwn_tm[i]=max(dwn_tm[i-1],up_tm[i])+cow[i].dwn;
    return dwn_tm[n];
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d%d",&cow[i].up,&cow[i].dwn);
    printf("%d",greedy());
    return 0;
}