01背包问题
思路
- 二维: 状态表示 定义 f[i][j] 表示 在考虑 第 i 个物品选或不选,总体积不超过j的集合区间。 选取所有选法的最大值
- 状态计算 : 不选 : f[i][j] = f[i -1] [j] 选 : f[i][j] = f[i - 1] [ j - v] + w;
- 决策 取 最大值 :选择 不选和 选两种状态下的最大值即可。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] v = new int[n + 1];
int[] w = new int[n + 1];
for (int i = 1; i <= n ; i ++) {
v[i] = sc.nextInt();
w[i] = sc.nextInt();
}
int[][] f = new int[n + 1][ m + 1];
for (int i = 1 ; i <= n ; i ++) {
for (int j = 1 ; j <= m; j ++) {
if (j < v[i]) f[i][j] = f[ i - 1][j];
if (j >= v[i]) f[i][j] = Math.max(f[i - 1][j] , f[i - 1][j - v[i]] + w[i]);
}
}
System.out.println(f[n][m]);
}
}
优化 为 一维dp
上面的状态计算 方程
不选 : f[i][j] = f[i -1] [j] 选 : f[i][j] = f[i - 1] [ j - v] + w;
i 状态都只与 i-1 这层状态相关。 可以用滚动数组进行优化。 不选 f[j] = f[j]
选 f[j] = f[j - v] + w;
为什么逆序 :保证上一层 v[i] 数据没有被污染 从后往前遍历。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] v = new int[n + 1];
int[] w = new int[n + 1];
for (int i = 1; i <= n ; i ++) {
v[i] = sc.nextInt();
w[i] = sc.nextInt();
}
int[]f = new int[ m + 1];
for (int i = 1 ; i <= n ; i ++) {
for (int j = m ; j >= v[i]; j --) {
f[j] = Math.max(f[j] , f[j - v[i]] + w[i]);
}
}
System.out.println(f[m]);
}
}