二维版:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N = 1010;
static int[][] dp = new int[N][N]; //dp[i][j] 只选前i件物品,体积 <= j的最优解
static int[] w = new int[N]; //存储价值
static int[] v = new int[N]; //存储体积
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException{
String[] init = in.readLine().split(" ");
int n = Integer.parseInt(init[0]);
int Vmax = Integer.parseInt(init[1]);
for(int i = 1;i <= n;i ++) {
init = in.readLine().split(" ");
v[i] = Integer.parseInt(init[0]);
w[i] = Integer.parseInt(init[1]);
}
for(int i = 1;i <= n;i ++) {
for(int j = 1;j <= Vmax;j ++) {
if (v[i] > j) { //当前背包装不下.最优解就是上一层的数据
dp[i][j] = dp[i - 1][j];
} else {
//装得下的话,背包的价值会变成dp[i - 1][j - v[i]] + w[i]
// j - v[i] 体积下的最优解 + w[i] 不一定会胜过dp[i - 1][j]
dp[i][j] = Math.max(dp[i-1][j], dp[i - 1][j - v[i]] + w[i]);
}
}
}
System.out.print(dp[n][Vmax]);
in.close();
}
}
f[i][j]:只从前i个物品全,总体积<=j的最优解。局部最优=>全局最优
一维版
由模拟二维的过程可知,通过不断覆盖前一维的状态,只一维数组也能实现
并且,并不是一维里的所有数据都需要更新,所以可以更新二维起始下标
二维更改一维需要满足条件,在决策dp[i][j]时,要能够知道dp[i - 1][j - v[i]]的状态
要用的是一行的数据,不能用当前行的数据
如表格中在决策第二件物品(v=2)时,dp[2]计算时,会把2更新成4,dp[4]计算时,需要用到上一次的2,而不是被更新过的4。所以决策时,每次都要用到前面的数据,但前面的数据又不能被改过。所以可以从后往前,可以确保你要决策的数,只被决策一次。
import java.io.*;
public class Main
{
static int N = 1010;
static int V;
static int n;
static int[] f = new int[N]; //只选前i件物品,背包容量为j的最优解
static int[] v = new int[N]; //存体积
static int[] w = new int[N]; //存价值
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args)throws IOException
{
String[] init = in.readLine().split(" ");
n = Integer.parseInt(init[0]);
V = Integer.parseInt(init[1]);
for(int i = 1;i <= n;i++){
String[] data = in.readLine().split(" ");
v[i] = Integer.parseInt(data[0]);
w[i] = Integer.parseInt(data[1]);
}
for(int i = 1;i <= n;i++){
//从后往前决策, j < v[i] 的地方不需要更新,直接用上一次的数据
for(int j = V;j >= v[i];j--){
f[j] = Math.max(f[j],f[j-v[i]]+w[i]);
}
}
System.out.println(f[V]);
in.close();
}
}