第 1 版:使用二维数组,不设置「哨兵」行
Java 代码:
import java.util.Scanner;
public class Main {
// 0-1 背包问题
// 判题地址:https://www.acwing.com/problem/content/description/2/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读第 1 行
int N = scanner.nextInt();
int V = scanner.nextInt();
// 读后面的体积和价值
int[] weight = new int[N];
int[] value = new int[N];
for (int i = 0; i < N; i++) {
weight[i] = scanner.nextInt();
value[i] = scanner.nextInt();
}
// 因为包含 0,所以 + 1
int[][] dp = new int[N][V + 1];
// 先写第 1 行
for (int j = 1; j <= V; j++) {
// 第 1 个物品的体积要小于等于背包容量
if (weight[0] <= j) {
dp[0][j] = value[0];
}
}
for (int i = 1; i < N; i++) {
for (int j = 0; j <= V; j++) {
dp[i][j] = dp[i - 1][j];
if (weight[i] <= j) {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
}
// 输出
System.out.println(dp[N - 1][V]);
}
}
第 2 版:使用二维数组,设置「哨兵」行
Java 代码:
import java.util.Scanner;
public class Main {
// 0-1 背包问题
// 判题地址:https://www.acwing.com/problem/content/description/2/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读第 1 行
int N = scanner.nextInt();
int V = scanner.nextInt();
// 读后面的体积和价值
int[] weight = new int[N];
int[] value = new int[N];
for (int i = 0; i < N; i++) {
weight[i] = scanner.nextInt();
value[i] = scanner.nextInt();
}
// 多开一行,避免对第 1 行单独赋值
// 后面要注意下标,有下标 weight[i] 和 value[i] 的地方都要减 1
int[][] dp = new int[N + 1][V + 1];
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
dp[i][j] = dp[i - 1][j];
if (weight[i - 1] <= j) {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - weight[i - 1]] + value[i - 1]);
}
}
}
// 输出
System.out.println(dp[N][V]);
}
}
第 3 版:状态压缩,从后向前写,因为压缩了行,相当于设置了「哨兵」行
Java 代码:
import java.util.Scanner;
public class Main {
// 0-1 背包问题
// 判题地址:https://www.acwing.com/problem/content/description/2/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读第 1 行
int N = scanner.nextInt();
int V = scanner.nextInt();
// 读后面的体积和价值
int[] weight = new int[N];
int[] value = new int[N];
for (int i = 0; i < N; i++) {
weight[i] = scanner.nextInt();
value[i] = scanner.nextInt();
}
// 状态压缩的写法:
int[] dp = new int[V + 1];
for (int i = 1; i <= N; i++) {
for (int j = V; j >= weight[i - 1]; j--) {
dp[j] = Math.max(dp[j], dp[j - weight[i - 1]] + value[i - 1]);
}
}
// 输出
System.out.println(dp[V]);
}
}