解题思路:
本题属于01背包问题,使用动态规划
dp[ j ]表示容量为 j 的背包的最大价值
注意:
需要时刻提醒自己dp[ j ]代表的含义,不然容易晕头转向
注意越界问题,且 j 需要倒序遍历
如果正序遍历
dp[1] = dp[1 - volume[0]] + value[0] = 15
dp[2] = dp[2 - volume[0]] + value[0] = 30
此时dp[2]就已经是30了,意味着物品0,被放入了两次,所以不能正序遍历。
为什么倒叙遍历,就可以保证物品只放入一次呢?
倒叙就是先算dp[2]
dp[2] = dp[2 - volume[0]] + value[0] = 15 (dp数组已经都初始化为0)
dp[1] = dp[1 - volume[0]] + value[0] = 15
所以从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int V = scan.nextInt();
int[] volume = new int[N];
int[] value = new int[N];
for (int i = 0; i < N; i++) {
volume[i] = scan.nextInt();
value[i] = scan.nextInt();
}
int[] dp = new int[V + 1];
for (int i = 0; i < N; i++) {
//注意越界问题,且 j 需要从大到小遍历
for (int j = V; j >= volume[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - volume[i]] + value[i]);
}
}
System.out.println(dp[V]);
}
}