动态规划 (三)经典背包

动态规划的学习进入了最后的阶段,现阶段还没有学习区域dp的相关内容,对于之前的动态规划简要做一下学习总结,和一些知识点,这次主要想总结一下背包问题,作为经典dp题,背包可以分为许许多多不同的题型:

  1. 01背包问题
  2. 完全背包问题
  3. 多重背包问题
  4. 分组的背包问题

一、01背包问题
作为最简单的背包问题,01背包思路也是最清晰的,也是最长遇见的,后面的背包问题都是由01背包演化而来的,所以01背包掌握非常重要!
01背包的动态转移方程为:(一定不能忘记定义的数组含义)
f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
在这个二维数组中for循环的顺序i:1-N,j:0-V,都是从小大排序
因为二维数组的定义占用内存太大,如果题目所需数据过大,会造成极大的不便,不过这样也存在着若干解决方法,最简单的就是在主函数之外进行定义,不过这样并不能从根源解决问题,只是能做到可以运行,没有达到省时的目的,所以我们换另一种思路,是否可以将二维数组更换为一维数组进行。
答案是可以的,但我们需要注意的是,如果我们定义的是一维数组,我们在for循环中j的次序需要改变顺序,由于二维数组中有i的顺序,在每一次的提取前一次的数据有i,但是由于变成一维数组后,缺少了i,也就是每一次在i中的循环,使用的都是新的数据。所以for循环要改变为V-0,从体积从大到小进行不断地重信定义,动态转移方程为:
f[v]=max{f[v],f[v-c[i]]+w[i]}

二、完全背包问题
完全背包问题与01背包问题的区别是,01背包的每个物品只有1个,然而完全背包的物品有无限个,但如果我们通过转化,便可以轻易的找到问题解决的方法,找出动态转移方程和for循环的次序,就可以轻易的拿下完全背包。
优化:
若两件物品i、j满足c[i]<=c[j] 并且w[i]>=w[j],则将物品j去掉,不用考虑
考虑到第i种物品最多选V/c[i]件,于是可以把第i种物品转化为V/c[i]件费用及价值均不变的物品,然后求解这个01背包问题
for,i:1-N,j: 0-V。
动态转移方程:
f[v]=max{f[v],f[v-cost]+weight
(这里仍然可以使用一维数组储存)
for i=1…N
for v=0…V
f[i][v]=max{f[i-1][v-kc[i]]+kw[i]|0=<k<=V/c[i]}
单独考虑f[i][v]时,二维形式就是:
f[i][v]=max{f[i-1][v-kc[i]]+kw[i]|k=0…m};m=V/c[i]

解析:
f[i][v]只与f[i-1][v]和f[i][v-c[i]]+w[i]有关。
考虑f[i][v]时,由于是从前往后写,一维数组表示的f[v]还没被写入,它表示的是f[i-1][v],而f[v-c[i]]已经被写入,它表示的是f[i][v-c[i]]

一维的
f[v]=max{f[v],f[v-c[i]]+w[i]}

表示的恰好是二维的
f[i][v]=max{f[i-1][v],f[i][v-c[i]]+w[i]}

三、多重背包问题
多重背包问题,可以简单理解01背包中的每个物品都是有限数量个,同样用数组存储。
优化:
用二进制思想。注意这儿要2^k中k的取值。大致取值意思为
k=0;sum=0;cnt=0;
while(1)
if(sum+2^k>n[i]) break; //
zopack[…][cnt++]=2^k;
sum+=2^k;
zopack[…][cnt++]=n[i]-sum; //
这里对于每一个n[i]都有一个zopack[];然后将每一zopack[][]看作01背包的每一个物品就可以按照01背包的思想做了。

四、分组的背包问题
将上面三种情况的背包组合成为一道题中。
算法:
这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值
状态方程:
f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i属于组k}

伪码:
for 所有的组k
for v=V…0
for 所有的i属于组k
f[v]=max{f[v],f[v-c[i]]+w[i]}
注意:“for v=V…0”这一层循环必须在“for 所有的i属于组k”之外。这样才能保证每一组内的物品最多只有一个会被添加到背包中。

总而言之,遇到背包问题,都是套模板就行,做得越多理解的越方便,希望下一张的练习题自己能做的更好!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值