POJ2184: Cow Exhibtion

概要

100個以下の要素からなる(S[i],F[i])の列がある.(-1000<=S[i],F[i]<=1000)
この列からいくつかの要素を選び,S[i],F[i]の総和をとる.
S[i]の総和とF[i]の総和が0を下回らないという条件のもとで,S[i]とF[i]の総和を最大にする.

解法

S[i]について降順にソート.
dp[i][j]:=(i番目までの要素を用いてS[i]の総和をjとするときのF[i]の総和の最大値.不可能なら負の無限大)
としてDP.

struct Cow{
    int s, f;
    Cow(int s, int f) : s(s),f(f) {}
    Cow() {}
};
bool operator<(const Cow &a, const Cow &b){
    if(a.s != b.s) return a.s < b.s;
    else return a.f < b.f;
}
int N;
Cow c[110];
int dp[2][100010];

const int INF = 100000000;
int main(){
    scanf("%d", &N);
    for(int i = 0; i < N; ++i){
        scanf("%d%d", &(c[i].s), &(c[i].f));
    }
    sort(c, c+N);
    reverse(c, c+N);
    dp[0][0] = 0;
    for(int i = 1; i < 100010; ++i) dp[0][i] = -INF;

    int *prev = dp[0], *next = dp[1];
    for(int i = 0; i < N; ++i){
        for(int j = 0; j <= 100000; ++j){
            next[j] = prev[j];
            if(0<=j-c[i].s && j-c[i].s<=100000 && prev[j-c[i].s] != -INF)
                next[j] = max(next[j], prev[j-c[i].s] + c[i].f);
        }
        swap(next, prev);
    }
    int res = 0;
    for(int i = 0; i <= 100000; ++i)
        if(prev[i] >= 0) res = max(res, i + prev[i]);
    printf("%d\n", res);
    return 0;
}

pairを使ったほうがよかった.