第六讲-分组的背包问题
题目
有n件物品可以被放入一个容量为v的背包中,每件物品体积为volume[i],价值为value[i].此外,这些物品被分成p组,每组中的物品最多只能选一件,求背包中最多可以装多少价值的物品.
分析
对于每组物品,可以选择这组物品中某一件,或者这组中一件也不选.
是不是感觉这个东西有点像,01背包?
如果用dp(k,v)表示前k组物品最多在容量为v的背包中装多少价值,那么显然
dp(k,v)=max(dp(k-1,v),dp(k-1,v-volume[i])+value[i]),其中i遍历第k个物品集合.
实现
for(int k=1;k<=p;k++)
for(int j=v;j>=0;j–) //此处遍历顺序与物品种类有关
for(int i:part[k])
dp[j]=max(dp[j],dp[j-volume[i]]+value[i]).
注意遍历方式一定是kji,如果是kij的话就无法保证每组只选一个了.
先j再i保证了每组内,每个体积只会被一个最优的物品访问到.
优化
这里可用第二讲完全背包中的对应优化
1.n^2遍历,将体积大价值小的物品去掉.
2.计数排序,去掉体积大于v的物品,相同体积的物品只取价值最大的.(限制物品个数大于体积的情况?)
其他
一点自己的看法
以上得思考都是基于01背包来做的,那么其他呢?
如果每组可以取无限次,每次取的物品可以不一样:分组就没有意义了,对所有物品完全背包即可.
如果每组可以取无限次,每次取的物品必须相同: 这是什么问题?想不出来,先略.
训练题
见后文