题意:每个数对有两个值,s,f,要求从所给数对中选出若干,使所有数对的s,f的和最大化的同时,保证所有s的和以及所有f的和不小于0。
思路:背包,以当前s的和作为状态下标,最大化t的和。因为这题存在负数的情况,做一个下标平移即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; } }