背包九讲笔记(一)

来源:互联网 发布:java中的日志级别 编辑:程序博客网 时间:2024/06/05 18:24

C表示费用(相当于体积),w表示价值

1.       01背包问题:每种物品只有一件,每件物品可放可不放

a.       f[ i ][ v ] = max { f[ i-1 ][ v ], f[ i-1 ][ v-c[i] ] + w[i] }

时间复杂度和空间复杂度都是O(n*v) 

b.      优化空间复杂度

需要保证在第i次循环结束后,f[ v ] 即是f[ i ][ v ]

这就要求用如下做法

for  i = 1..N

                for v = V..0

                                f[v] = max{ f[v], f[ v-c[i] ] + w[i] } ;

转移方程 f[v] = max{ f[v], f[ v-c[i] ] + w[i] }

c.       实现

ZeroOnePack(cost, wight)表示处理一件物品

ZeroOnePack(cost, weight)

{

for  v = V..cost

                f[v] = max{ f[v], f[v-cost] + weight };

}

于是,整个问题写成

for  i = 1..N

                ZeroOnePack(c[i], w[i]);

d.      细节

初始化时,f[0] = 0 f[1..V] = -

2.       完全背包问题:每件物品个数无限

a.       可以转化为01背包问题,但是效率非常低

b.      优化1

如果两件物品i, j c[i]<=c[j]w[i]>=w[j],则一定不用考虑j

此方法对随机数据有效果,对特殊数据没有意义

c.       优化2:二进制思想

将第i种物品拆分成费用c[i]*2k,价值w[i]* 2k的若干件商品,因为不管实际上要选择多少件物品i,都可以用这若干件新的物品i组合而成。每样物品拆分成了O( log(V/c[i]) )件物品

for i = 1..N

                for v = 0..V

                                f[v] = max{ f[v], f[v-cost] + weight }

d.      实现

CompletePack(cost, weight)

{

                for v = cost..V

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

}

 

3.       多重背包问题:第i样物品最多n[i]

a.       基本算法

和完全背包类似,f[i][v] 表示前i种物品恰好放入容量为v的背包的最大价值

F[i][v] = max{ f[i-1][ v-k*c[i] ] + k*w[i] }  (0<=k<=n[i])

复杂度O( V*n[i] )

b.      转化为二进制思想的01背包,复杂度为O( V*∑log n[i] )

c.       实现

处理一种物品的多重背包问题过程

MutiplePack(cost, weight, amount)

{

                if (cost*amount>=V ) // 如果总体积大于包的大小,相当完全背包问题

                {

                                CompletePack(cost, weight);

                                return

}

int k = 1;

// init

while (k<num)

{

                ZeroOnePack(k*cost, k*weight)

amount -= k

k*=2

}

ZeroOnePack(amount*cost, amount*weight)

}

原创粉丝点击