首页 > 代码库 > 完全背包

完全背包

完全背包问题
与01背包的区别
01背包:每种物品只能取一件
完全背包:每种物品能取无限件

按照01背包思路的状态转移方程
f[i][v] = max{f[i-1][v-k*c[i]] + k*w[i] | 0 <= k*c[i] <= v};

完全背包转化为01背包的思路
将一种物品拆成多件物品

二进制思想
第i种物品拆成费用为 c[i]*2^k, 价值为 w[i]*2^k 的若干件物品, c[i]*2^k <= V

c[i] * n = V
n = V/c[i]
n = 2^k
2^k = V/c[i]
k = log(V/c[i])

选n件第i种物品,可以表示为 选2^k件第i种物品
最优策略为若干个2^k件物品的和 若干个--若干种物品 每种物品2^k个

复杂度:O(log V/c[i])

O(VN)的算法

//O(VN)算法的伪代码
for i = 1..N
for v = 0..V
f[v] = max{f[v],f[v-cost]+weight}
//对比01背包的伪代码
for i = 1..N
for v = V..0
f[v] = max{f[v],f[v-cost]+weight}

 

* 回顾01背包的思路
在要装入的物品顺序一定时,背包某一时刻的体积是固定的,可以直接对应背包中装入的物品,确保判断第i种物品是否装入时,已经对第i-1种物品判断过了,每种物品只执行一次。f[i-1][v-c[i]]已经确定第i种物品只能装入的体积为c[i]。

* O(VN)的思路
加选第i种物品,需要一个可能已选入第i种物品的子结果f[i][v-c[i]],没有限定第i种物品的加入的体积大小

## O(VN)的状态转移方程
_f[i][v] = max{f[i-1][v],f[i][v-c[i]]+w[i]}_

//与当前的背包的最大价值相比较,如果再加入一件该物品后背包的最大价值 f[v-c[i]]+w[i] 变得更大,就加入,
procedure CompletePack(cost,weight)
for v = cost..V
f[v] = max{f[v],f[v-c[i]]+w[i]}

 


拆分成的子问题是:在背包的容量为任意值时,是否要加入当前的这个物品

完全背包