01背包:每个背包要与不要两种可能性展开
有依赖的背包:多个物品变成一个复合物品(互斥),每件复合物品要和怎么要多种可能性展开
不能用01背包来解,但是非常重要的问题:非负数组前k个最小的子序列和问题
题目一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| class Main {
public static int MAXM = 101; public static int MAXT = 1001; public static int[] cost = new int[MAXM]; public static int[] val = new int[MAXM]; public static int[] dp = new int[MAXT]; public static int t, n;
public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StreamTokenizer in = new StreamTokenizer(br); PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); while (in.nextToken() != StreamTokenizer.TT_EOF) { t = (int) in.nval; in.nextToken(); n = (int) in.nval; for (int i = 1; i <= n; i++) { in.nextToken(); cost[i] = (int) in.nval; in.nextToken(); val[i] = (int) in.nval; } out.println(compute1()); } out.flush(); out.close(); br.close(); }
public static int compute1() { int[][] dp = new int[n + 1][t + 1]; for (int i = 1; i <= n; i++) { for (int j = 0; j <= t; j++) { dp[i][j] = dp[i - 1][j]; if (j - cost[i] >= 0) { dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - cost[i]] + val[i]); } } } return dp[n][t]; } }
|
题目二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
public class Main {
public static int MAXN = 501;
public static int MAXX = 100001;
public static int[] cost = new int[MAXN];
public static long[] val = new long[MAXN];
public static long[] dp = new long[MAXX];
public static int n, m, x;
public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StreamTokenizer in = new StreamTokenizer(br); PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); while (in.nextToken() != StreamTokenizer.TT_EOF) { n = (int) in.nval; m = 1; in.nextToken(); x = (int) in.nval; long ans = 0; long happy = 0; for (int i = 1, pre, cur, well; i <= n; i++) { in.nextToken(); pre = (int) in.nval; in.nextToken(); cur = (int) in.nval; in.nextToken(); happy = (long) in.nval; well = pre - cur - cur; if (well >= 0) { x += well; ans += happy; } else { cost[m] = -well; val[m++] = happy; } } ans += compute(); out.println(ans); } out.flush(); out.close(); br.close(); }
public static long compute() { Arrays.fill(dp, 0, x + 1, 0); for (int i = 1; i <= m; i++) { for (int j = x; j >= cost[i]; j--) { dp[j] = Math.max(dp[j], dp[j - cost[i]] + val[i]); } } return dp[x]; }
}
|
题目三
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| import java.util.HashMap;
class Solution { public static int findTargetSumWays(int[] nums, int target) { int sum = 0; for (int n : nums) { sum += n; } if (sum < target || ((target & 1) ^ (sum & 1)) == 1) { return 0; } return subsets(nums, (target + sum) >> 1); }
public static int subsets(int[] nums, int t) { if (t < 0) { return 0; } int[] dp = new int[t + 1]; dp[0] = 1; for (int num : nums) { for (int j = t; j >= num; j--) { dp[j] += dp[j - num]; } } return dp[t]; }
}
|