问题描述:
背包的容量是V,能承受的最大的重量是M
有N个物品,v, m, w数组中分别存放着每个物品的体积,重量,价值
求解将哪些物品装入背包,可使物品总体积不超过背包容量,物品的总重不超过背包能承受的最大重量,且总价值最大
思路分析:
方案一:
dp数组的含义是:背包在一定的体积和重量下,可以获得的最大价值
假设现在要装第i件物品,那么dp[i - 1]储存的就是装这件物品之前的所有物品可以获得的最大价值,通过装第i件物品,实现dp[i]的更新,更新为包括第i件物品可以获得的最大价值。所以下面的代码对应的是dp[i - 1]
在体积为j,重量为k的条件下,装入第i件物品,体积得腾出v[i],重量也得腾出m[i],这样才可以装下第i件物品,如果可以装下,那么背包的价值在 dp[i - 1][j - v[i]][k - m[i]] 的条件下增加了w[i],和之前的进行比较,选出最优解
dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - v[i]][k - m[i]] + w[i]);
优化版:
和之前的一样,咱们需要的数据只有dp[i - 1],如果从后往前遍历就不会破坏原来的dp[i - 1]数据
dp[j][k] = Math.max(dp[j][k], dp[j - v[i]][k - m[i]] + w[i]);
代码:
public class Main {
int N; //有N个物品
int V; //背包的容量为V
int M; //背包能承受的最大重量
int[] v; //每个物品的体积
int[] m; //每个物品的重量
int[] w; //每个物品的价值
public int two_dimension1(){
int[][][] dp = new int[N + 1][V + 1][M + 1];
for(int i = 1; i <= N; i++){
for(int j = 1; j <= V; j++){
for(int k = 1; k <= M; k++){
if(j < v[i] || k < m[i]){
dp[i][j][k] = dp[i - 1][j][k];
}
else{
dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - v[i]][k - m[i]] + w[i]);
}
}
}
}
return dp[N][V][M];
}
//优化
public int two_dimension2(){
int[][] dp = new int[V + 1][M + 1];
for(int i = 1; i <= N; i++){
for(int j = V; j >= 1; j--){
for(int k = M; k >= 1; k--){
if(j < v[i] || k < m[i]){
dp[j][k] = dp[j][k];
}
else{
dp[j][k] = Math.max(dp[j][k], dp[j - v[i]][k - m[i]] + w[i]);
}
}
}
}
}
}