0-1背包问题的图解过程

心心念的0-1背包问题

书上给出题解流程:
在这里插入图片描述


转换成我们的语言=>
If(背包容量装不下第i个物品){
既然装不下第i个物品,那么装入前i个物品的最大价值就等于装下前i-1个物品的价值 }else(背包容量可以装下第i个物品){
很开心可以增加价值了,但是我这心里有点犯嘀咕,会不会我这放入第i个物品后,第i个物品不仅价值低,而且占地方还大,我是不是还要和装入前i-1个物品的价值进行比较,择优选择所以:
Max(只装入前i-1个物品的价值,装入i后的价值+前i-1个物品的价值在减去第i个物品价值的容量下的值)
}
//这里注意第二步中把前i-1个物品的价值在减去第i个物品价值的容量下的值,并不是每次都要把前i-1个物品的价值加起来,也有例外,比如剩下的空间不能同时放完前i-1个物品的价值,此时实际上会去比较前i-2个物品和第i-1个物品的是否在之前能够装下第i-1个物品,说着像递归,来张图方便理解:

在这里插入图片描述

图中黄色标注部分为容器的容量,灰色标注的为价值。
为了方便说明,我们找两个坐标值进行说明
1.我们以装入第3个物品到容量为8的容器中为例(图中的红圈部分),因为背包的容量可以装下第3个物品,那么我们分两种情况
    1)装下3,如果装下3,那么容器剩余8-6=2个容量大小,我们要去找前2个元素能否都装下,所以我们找到了红线箭头指向的部分,即[2][2]的位置,这里的价值为6,那么这时最大的价值是5+6=11
    2)不装3,看看前i-1个元素的价值是多少,我们找到是9,即红圈对应的上面一格
好了我们求最大值max(11,9)=11所以在有三个物品可以选择,容量为8的容器中可以装下的最大价值是11

2.我们接着以橙色的小圈为例,此时背包容量是10,要去装第3个物品,首先背包容量是可以装入大小6的物品,所以又得分两种情况:
a)装下第三个物品,如果装下第3个物品,那么剩余容量是10-6=4,前3-1个元素的在4空间大小是不是都能装下我们找下标[2][4]=9,如此得到总价值5+9=14
b)不装,那么找前3-1个元素在容量 大小为10的最大价值,得到[2][10]=9
那么,最后的结果是max(14,9)=14

其它情况依次类推…
在代码实现之前请注意两个问题:
1.实际上在上述的表格中,我们最需要的是最右下角的那个值,那个值代表了最大价值。
2.而且最优解一定会是求max[前值,后值]中的后值,为啥呐?
可能有朋友会提出,如果max[前值,后值]中的后值最大,那么直接将这句改成直接求后面不久行了,下面给出测试的代码
val[i][j]=Math.max(val[i-1][j],value[i-1]+val[i-1][j-weight[i-1]]);
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 6 6 6 6 6 6 6 6 6
// 0 0 6 6 9 9 9 9 9 9 9
// 0 0 6 6 9 9 9 9 11 11 14
// 0 0 6 6 9 9 9 10 11 13 14
// 0 0 6 6 9 9 12 12 15 15 15
val[i][j]=value[i-1]+val[i-1][j-weight[i-1]];
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 6 6 6 6 6 6 6 6 6
// 0 0 3 3 9 9 9 9 9 9 9
// 0 0 3 3 9 9 5 5 8 8 14
// 0 0 3 3 9 4 4 7 7 13 13
// 0 0 3 3 6 6 9 9 15 10 10
最通俗的解释,就像站在前人的肩膀上寻找最优解,这里巨人的肩膀就是前值。从在这个列表中看,同一列的值上面的总是小于等于下面的也可看出一些端倪,为哈要提这一点因为最后我们看看是哪种搭配组合可以得到最大值,我们要把这个组合输出出来。

代码部分:

public static void main(String[] args) {
   
		// TODO Auto-generated method stub
		int[] weight = {
    1, 4, 3 };// 每个小物品的容量
		int[] value = {
    1500, 3000, 2000 };// 每个小物品的价值
		// 构造这个求解表
		
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值