POJ 2184(DP

题意:每个数对有两个值,s,f,要求从所给数对中选出若干,使所有数对的s,f的和最大化的同时,保证所有s的和以及所有f的和不小于0。

思路:背包,以当前s的和作为状态下标,最大化t的和。因为这题存在负数的情况,做一个下标平移即可。

import java.util.*;
import java.io.*;
import java.math.*;

public class Main {
    public static final int maxv = 200005;
    public static final int shift = 100000;

    public static void main(String[] args) throws Exception {
        Scanner in = new Scanner(new File(
                "/home/develop/eclipse_file/ACMproject/src/in"));
        // Scanner in=new Scanner(System.in);
        int N = in.nextInt();
        dat[] sc = new dat[N];
        for (int i = 0; i < N; i++) {
            sc[i] = new dat();
            sc[i].s = in.nextInt();
            sc[i].f = in.nextInt();
        }
        Arrays.sort(sc, new cmp());
        int[] dp = new int[maxv];
        for (int i = 0; i < maxv; i++)
            dp[i] = (int) -1e9;
        dp[shift] = 0;
        for (int i = 0; i < N; i++) {
            if (sc[i].s > 0) {
                for (int j = maxv - 1; j >= 0; j--) {
                    if (j - sc[i].s >= 0)
                        dp[j] = Math.max(dp[j], dp[j - sc[i].s] + sc[i].f);
                }
            } else {
                for (int j = 0; j < maxv; j++) {
                    if (j - sc[i].s < maxv)
                        dp[j] = Math.max(dp[j], dp[j - sc[i].s] + sc[i].f);
                }
            }
        }
        int ans = (int) -1e9;
        for (int i = shift; i < maxv; i++) {
            if (dp[i] >= 0)
                ans = Math.max(ans, dp[i] + i - shift);
        }
        System.out.println(ans);
        in.close();
    }
}

class dat {
    int s, f;
}

class cmp implements Comparator<dat> {
    public int compare(dat a, dat b) {
        return a.s - b.s;
    }
}
View Code

 

posted @ 2015-06-18 01:07  PlusSeven  阅读(106)  评论(0编辑  收藏  举报