直接上代码:
package dynamic;
public class beibaoProblem {
public static void main(String[] args) {
/**
背包问题需要满足三个公式
1.v[i][0]=v[0][j]=0
2.当新加入商品的重量超过背包的容量,则当前背包最大价值就是前面的情况,即v[i][j]=v[i-1][j],
也就是背包容量为j,能容纳前i-1个商品的最大价值
3.当新加入商品的重量不超过背包的容量,则当前背包最大价值就是,
v[i][j]=max{v[i-1][j],val[i]+v[i-1][j-w[i]]}
max{上一个情况,当前商品i的价值+上一个情况}
*/
/*
商品 1 2 3
重量1 4 3
价值 1500 3000 2000
*/
int[] w={1,4,3};//重量
int[] val={1500,3000,2000};//价值
int m=4;//背包的容量
int n=val.length;//物品个数
int[][] v=new int[n+1][m+1];//int[i][j]表示前i个物品放进容量为j的背包的最大价值
//用来记录存放商品的情况
int[][] path=new int[n+1][m+1];
//下面两个for循环进行初始化,把第一行和第一列全部置为0,也可以不进行初始化,因为数组在生命的时候默认值为0
for (int i=0;i<v.length;i++){
v[i][0]=0;
}
for (int i=0;i<v[0].length;i++){
v[0][i]=0;
}
for (int j = 1; j <v[0].length ; j++) {
for (int i = 0; i < v.length - 1; i++) {
if (w[i] <= j) {
//v[i + 1][j] = Math.max(v[i][j], val[i] + v[i][j - w[i]]);
//为了记录存放商品情况,不能简单使用上面公式,可以使用If else进行
if (v[i][j]<val[i] + v[i][j - w[i]]){
v[i + 1][j]=val[i] + v[i][j - w[i]];
//进行记录到path数组中
path[i + 1][j]=1;
//当前情况是改变了以后的最优解
}else {
v[i + 1][j]=v[i][j];
}
} else {
v[i + 1][j] = v[i][j];
}
}
}
for (int i=0;i<v.length;i++){
for (int j=0;j<v[i].length;j++){
System.out.print(v[i][j]+" ");
}
System.out.println();
}
/*for (int i=0;i<path.length;i++){
for (int j=0;j<path[i].length;j++) {
if (path[i][j] == 1) {
System.out.println("第" + i + "个商品放入背包");
}
}
}
这种情况的输出是:
第1个商品放入背包
第1个商品放入背包
第1个商品放入背包
第1个商品放入背包
第2个商品放入背包
第3个商品放入背包
第3个商品放入背包
*/
/*因为不是只有最后一次才会 v[i + 1][j]=val[i] + v[i][j - w[i]];
//进行记录到path数组中
path[i + 1][j]=1;
进行这种操作。
所以我们进行倒续遍历
*/
int i= path.length-1;//行的最大下表
int j= path[0].length-1;//列的最大下标
while(i>0&&j>0){
if (path[i][j]==1){
System.out.println("第"+i+"个商品放入背包");
j=j-w[i-1];//第i个商品的重量是w[i-1]
}
i--;
}
}
}