题目
第一种解法
- 第一层循环 控制着放入的物品
- 第二层循环 控制着背包的重量
- 第三层循环 控制着放入背包物品的数量. 第一行第一列全为0,方便我们计算
- 递推的关系式为dp[i+1][j] = Math.max(dp[i+1][j],dp[i][j-k * w[i]]+k*v[i]);
- kv[i]:选取k当前物品的价值 j-k*w[j] :当前背包还剩余可放入的重量
- dp[i][j-kw[i]]:表示去上一件物品选取j- k w[i]重量的价值
代码如下
public static int getMax(int n,int W,int[] w,int[] v){
int[][] dp = new int[n+1][W+1];
for(int i = 0;i < n;i++) {
for(int j =0;j <= W;j++) {
for (int k = 0; k *w[i]<=j; k++) {
dp[i+1][j] = Math.max(dp[i+1][j],dp[i][j-k*w[i]]+k*v[i]);
}
}
}
for (int i = 0; i < dp.length; i++) {
System.out.println(Arrays.toString(dp[i]));
}
return dp[n][W];
}
第二种解法
- 如果背包重量<物品的重量,dp[i][j] 就直接从上一件物品选取
- 如果背包重量>物品的重量 递推关系式: Math.max(dp[i][j],dp[i+1][j-w[i]]+v[i]);
- dp[i+1][j-w[i]]: 从当前物品选取还能放入背包。 j-w[i]:还能放入背包的重量
- 因为 动态规划的求解,都是根据上一层的解来进行的。
代码如下
public static int getMax1(int n,int W,int[]w,int[]v){
int[][] dp = new int[n+1][W+1];
for (int i = 0; i < n; i++) {
for (int j = 0; j <=W; j++) {
if(j<w[i]){
dp[i+1][j] = dp[i][j];
}else{
dp[i+1][j] = Math.max(dp[i][j],dp[i+1][j-w[i]]+v[i]);
}
}
}
for (int i = 0; i < dp.length; i++) {
System.out.println(Arrays.toString(dp[i]));
}
return dp[n][W];
}
第三种解法 重复利用数组
public static int getMax2(int n,int W,int[] w,int[]v){
int[] dp = new int[1001];
for (int i = 0; i < n; i++) {
for (int j = w[i]; j <=W ; j++) {
dp[j] = Math.max(dp[j],dp[j-w[i]]+v[i]);
}
}
return dp[W];
}