1.题目
2.基本思想
- 状态 f[i][j] 定义:前 i 个物品,背包容量 j下的最优解(最大价值):
当前的状态依赖于之前的状态,可以理解为从初始状态 f[0][0] = 0 开始决策,有 N件物品,则需要 N 次决 策,每一次对第 i件物品的决策,状态 f[i][j] 不断由之前的状态更新而来。 -
- f[i][0]=f[0][j]=0 //第一行第一列为0
-
- j < v[i],(当前背包容量不够没得选),因此前 i个物品最优解即为前 i−1个物品最优解:  : 即:f[i][j] = f[i - 1][j]。
-
- j >= v[i]背包容量够可以选,因此需要决定选与不选第 i个物品:
选:f[i][j] = f[i - 1][j - v[i]] + w[i]。不选:f[i][j] = f[i - 1][j]。
- j >= v[i]背包容量够可以选,因此需要决定选与不选第 i个物品:
3. 代码实现
二维DP
public class _2背包问题_01背包 {
/*
* dp[i][j] 表示为前i个物品j重量的最大价值
* ① 当v[i]>j 剩下容量放不进去 直接继承 前i-1件的最大价值 dp[i][j]=dp[i-1][j]
* ② 当v[i]<=j 有两种选择 当前物品放进去和不放进去
* ③放进去 dp[i][j]=dp[i-1][j-v[i]]+w[i];
* ④不放进去 dp[i][j]=dp[i-1][j]
*/
public static void main(String[] args) {
//输入
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
int V= 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 [][]dp=new int[N+1][V+1];
for (int i = 1; i <=N ; i++) {
for (int j = 0; j <=V; j++) {
if (j>=v[i])
// 当前背包容量能装进第i个物品,则价值选和不选去Max值
dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
else
// 当前背包容量装不进第i个物品,则价值等于前i-1个物品
dp[i][j]=dp[i-1][j];
}
}
System.out.println(dp[N][V]);
}
}
空间优化一维DP
public class _2背包问题__01背包_优化成一维数组 {
public static void main(String[] args) {
/*
* (1) 如果不装第 i 件物品,那么问题就转化为“前 i−1 件物品放入容量为 j的背包中的最大价值”
(2) 如果装第 i件物品,那么问题就转化为“前 i−1 件物品放入剩下的容量为 j−v[i] 的背包中的最大价值”
*/
Scanner sc = new Scanner(System.in);
int N=sc.nextInt();
int V=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[] dp=new int[V+1];
dp[0]=0;
for(int i=1;i<=N;i++) {
//采取逆序的方式
//假如枚举到:i = 3, j = 8, v[3] = 5, w[3] = 1
//二维:dp[3][8] = max(dp[2][8], dp[2][3] + w[3]) 此时的dp[2][8]和dp[2][3]都是上一轮的状态值
//一维:dp[8] = max(dp[8], dp[3] + w[3]) 我们要保证dp[8]和dp[3]都是上一轮的状态值
//按照逆序的顺序,一维dp数组的更新顺序为:dp[8], dp[7], dp[6], ... , dp[3]
//如果按照顺序进行更新,dp[3] = max(dp[3], dp[0] + w[0]),对dp[3]的状态进行了更新,
//那么在更新dp[8]时,用到的dp[3]就不是上一轮的状态了,不满足动态规划的要求。
for(int j=V;j>=v[i];j--) {
dp[j]=Math.max(dp[j], dp[j-v[i]]+w[i]);
}
}
System.out.println(dp[V]);
}
}