关于背包问题的思考
Demo
背包的容量M=8,物品的种类=4,四个物品的体积依次为2、3、4、5,他们的价值依次为3、4、5、6,求出背包所装载物品的最大价值?
物品价值与体积对照表
物品 | 体积 | 价值 |
---|---|---|
1 | 2 | 3 |
2 | 3 | 4 |
3 | 4 | 5 |
4 | 5 | 6 |
代码思路我是从这个博客上找的
经典算法总结——背包问题(java实现)【已完结】
代码
// An highlighted block
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] weight={2,3,4,5};
int [] value={3,4,5,6};
System.out.println(find(8,4,weight,value));
}
public static int find(int V,int N,int[] weight,int[] value){
//初始化动态规划数组
int[][] dp = new int[N+1][V+1];
//为了便于理解,将dp[i][0]和dp[0][j]均置为0,从1开始计算
for(int i=1;i<N+1;i++){
for(int j=1;j<V+1;j++){
//如果第i件物品的重量大于背包容量j,则不装入背包
//由于weight和value数组下标都是从0开始,故注意第i个物品的重量为weight[i-1],价值为value[i-1]
if(weight[i-1] > j)
dp[i][j] = dp[i-1][j];
else
dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-weight[i-1]]+value[i-1]);
}
}
for(int i=0;i<N+1;i++)
{
for(int j=0;j<V+1;j++)
{
System.out.print(dp[i][j]+" ");
}
System.out.println("");
}
return dp[N][V];
}
}
可以通过下面代码打印的二维数组分析这个动态规划过程,我们可以看到这是一个5行9列的二维数组,行数是代表有几个物品可以供选择,列数代表背包的容量是多少。我们可以举几个例子来看一看,例如第三行第六列的7,由于处于第六列,说明此时它的容量为五,处于第三行,说明此时可供他选择的物品有前两种,通过状态方程:dp[i][j] = (dp[i-1][j] > (dp[i-1][j-weight[i]]+value[i]))? dp[i-1][j]:(dp[i-1][j-weight[i]]+value[i]) ,可以分析出它存入的是价值为4的第二个物品和第二行第二列的价值所代表的物品,而第二行第二列的物理意义是只有一个空间为2的位置和只有第一个物品可供选择。再例如第五行第八列的价值9,由于处于第八列说明此时它的容量为七,处于第五行,则可供选择的物品是前四个及所有物品,而该位置的价值选择就是选取了第四个物品和第三行第二列的价值所代表的物品,第三行第二列的物理意义是可以选择前三种物品,但是容量只有二,所以只能选择价值为3,体积为2的第一种商品。
0 0 0 0 0 0 0 0 0
0 0 3 3 3 3 3 3 3
0 0 3 4 4 7 7 7 7
0 0 3 4 5 7 8 9 9
0 0 3 4 5 7 8 9 10