背包9讲——01背包问题及变种题目


力扣上刷了快200道题了,动态规划的题也做了很多,但是发现自己始终不得其精髓,有些奇奇怪怪的题可以转化为动态规划问题,但是没有经过系统训练就是不知道,就算看到答案也是看不懂;
网上类似的讲解很多很多,我这里只是总结其他人的观点,再融入自己见解,主要目的是对学习过程进行记录,而不是搞出一些新的知识点;欢迎各位能在我理解的基础上更进一步,总结出自己的学习方法和思路;

经典题目

有容量为n的容器。有很多种物体,第i件物品对应的体积和价值分别是Vi及Wi,每种物品仅有一件,可以选择放或者不放,问将那些物体放入背包会使得总价值最大。

基本思路

根据动态规划一般思路,需要给出状态转移方程,这玩意儿感觉就跟数学里面的归纳法一样,就是需要给出一系列数字中后一个跟前一个关系;那么问题是这一系列数怎么选才能让他们有规则呢?
对于我这种数学成绩很差的人来说只能穷举了,一个一个看,一个一个总结。
如果对于前i-1件物品恰好放进一个容量为v的背包的最大价值是F[i-1][v],那么对于第i个物体,同样大小的背包,我们可以选择放或者不放。
如果放,那么
F [ i ] [ v ] = F [ i − 1 ] [ v − V i ] + W i F[i][v]=F[i-1][v-Vi]+Wi F[i][v]=F[i1][vVi]+Wi
其中Vi代表第i个物体的体积,Wi代表第i个物体的价值,F[i-1][v-Vi]代表如果前i-1个物体中如果背包体积v-Vi情况下最大的价值
如果不放,那么
F [ i ] [ v ] = F [ i − 1 ] [ v ] F[i][v]=F[i-1][v] F[i][v]=F[i1][v]
因此我们只需要取较大值就可以,可以写做
F [ i ] [ v ] = m a x ( F [ i − 1 ] [ v ] , F [ i − 1 ] [ v − V i ] + W i ) F[i][v]=max(F[i-1][v],F[i-1][v-Vi]+Wi) F[i][v]=max(F[i1][v],F[i1][vVi]+Wi)
除此之外,在栈空间中声明的对象需要全部初始化为0,并没有什么额外的条件;

我们注意到上面其实是有依赖关系的,也就是说我们在找F[i][v]的时候必须事先知道F[i-1][v]及F[i-1][v-Vi],也就是对于大的i和v都依赖于更小的i和v,因此可以从0——max进行两层循环,伪代码如下:
在这里插入图片描述

空间优化

其实上面的过程一维数组就能实现,我们选择只保留背包大小这一个维度,那我们的状态转移方程就可以这样写:
F [ v ] = m a x ( F [ v ] , F [ v − V i ] + W i ) F[v]=max(F[v],F[v-Vi]+Wi) F[v]=max(F[v],F[vVi]+Wi)
上面的方程什么时候会与
F [ i ] [ v ] = m a x ( F [ i − 1 ] [ v ] , F [ i − 1 ] [ v − V i ] + W i ) F[i][v]=max(F[i-1][v],F[i-1][v-Vi]+Wi) F[i][v]=max(F[i1][v],F[i1][vVi]+Wi)
等价呢? 当我们访问到的F[v]都是i-1对应的f[v]时,那我们就可以推出下一个时候的最大价值。
那我们怎么保证我们每次访问的都是i-1的呢,本来不同的i值对应一个值,现在同一个v下只用一个一个值来代表整个不同i对应的数组;我们只需要保留i-1时候,本来我们计算后面的i需要依赖前面的i值刷新;但是如果我们从大到小遍历v,那么当到i到时候,i-1对应的值并没有被刷新,也就达到了我们的目的;
这样伪代码如下:
在这里插入图片描述

变种题目

在这里插入图片描述
这里要求我们把一个数组分成两组使其和相等,我们可以先求和,然后判断是否为偶数,如果为偶数,那么我们可以这样想:
将和除以二得到的数记为targetnum;
背包的容量就是数组的长度;每个物体的体积就是1,价值就是对应的数,我们只需要按照01背包问题进行查找,看看能否找到放进去的物体价值刚好等于targetnum;如果有,则返回真,如果无则返回false;
放上链接,快去做一做吧:
https://leetcode-cn.com/problems/partition-equal-subset-sum/
https://leetcode-cn.com/problems/ones-and-zeroes/

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无情の学习机器

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值