01背包问题:
背包问题算是动态规划中,最经典的题目了,分为01背包,和完全背包问题,不过两者有比较密切的关系,01背包搞明白了,完全背包自然迎刃而解,下面和大家共同探索一道01背包最大价值问题。
题目描述:
有一下商品,价值和重量如表所示,问给定一个重量为4的背包,怎样装东西,能使获得的价值最大。
商品 | 价值 | 重量 |
手机 | 1500 | 1 |
吹风机 | 800 | 2 |
平板 | 2000 | 2 |
解决此问题时,最好借用画表的方法,由于本人也是刚开始学,所以把想法说明下。
咱们先建立一个二维数组dp[i][j],w[i]表示第i件商品的重量,背包重量W,用来表示前i件商品中获得的最大价值。
刚开始一件商品也不选,则背包内价值为0,也就是二维数组的第一行全0(dp[0][j]),同样的假设背包重量为0,则一件商品也装不进去,所以第一列全为0(dp[i][0]),初始化第一行和第一列后,开始依次往背包放东西。
第一次只允许第一件商品放入,则在第一行所有重量满足的情况下,都将获得第一件商品的价值。
接下来允许放入两件商品,同理在重量满足的情况下,需考虑是否将第二件商品放入背包,这就需要比较,前i件商品的价值,与加上背包的价值,哪个价值更大。由此可以有以下代码:
public class test12 {
public static void main(String[] args) {
int[]w={1,2,2};//物品的重量
int[]val={1500,800,2000};//物品的价值
int m=4;//背包的重量
int n=val.length;
int[][]v=new int[n+1][m+1];//二维数组,用来表示前i件商品的最大价值
int[][]path=new int[n+1][m+1];//用来记录哪个商品被放入背包
for(int i=1;i<v.length;i++){//这里从i=1,j=1开始遍历,和商品对应
for(int j=1;j<v[0].length;j++){
if(w[i-1]>j){//当商品重量大于背包重量
v[i][j]=v[i-1][j];
}
else{//当背包重量大于商品重量时
if(v[i-1][j]<val[i-1]+v[i-1][j-w[i-1]]){//判断在剩下的重量 选择放还是不放,要比较价值的大小,不放时和放时
v[i][j]=val[i-1]+v[i-1][j-w[i-1]];
path[i][j]=1;//选择了放,将放入的进行标记
}
else{//没有放进去
v[i][j]=v[i-1][j];
}
}
}
}
System.out.println(v[n][m]);//打印最大价值
for(int i=0;i<v.length;i++){//输出价值表
for(int j=0;j<v[0].length;j++){
System.out.print(v[i][j]+" ");
}
System.out.println();
}
System.out.println("--------------------");
int s=path.length-1;
int q=path[0].length-1;
while(s>0&&q>0){//判断输出选择的商品,这里从后往前遍历,否则有冗余情况
if(path[s][q]==1){
System.out.println("把第"+s+"个装入背包内");
q-=w[s-1];//将最后放进去后,重量将发生变化,求剩余重量
}
s--;//下一个商品
}
}
}
结果如下:
扫描二维码关注公众号,回复:
15188442 查看本文章