背包问题
01背包问题:每件物品只有一件,可以选择放或不放(即取0件或1件,故名01)
代码很短:
1、最多能创造多少价值?
初始化:
for(int v=0;v<=V;++v) d[v]=0;
代码:
for(int i = 0; i < N; i++) for(int v = c[i] ; v < V; v++) d[i][v] = max{d[i-1][v], d[i-1][v-c[i]]+w[i]};
优化空间后的如下:
for(int i = 0; i < N; i++) for(int v = V ; v >=c[i]; v--) d[v] = max{d[v], d[v-c[i]]+w[i]};
2、背包放满时,最多(最少)能创造多少价值?
这个问题的前提是背包必须要放满,所以我们的初始条件要改变,原来我们可以一件东西都不放,这是最大的价值是0,但在这个问题下是不允许的
所以只有在容量为0时最大价值为零,即d[0] = 0,将其他设为-∞,这样循环下来只有当包的容量恰好填满的时候d[v]才有值。
初始化:
d[0]=0; for(int v=1;v<=V;++v) d[v]=-∞;
其他不变:
for(int i = 0; i < N; i++) for(int v = V ; v >=c[i]; v--) d[v] = max{d[v], d[v-c[i]]+w[i]};
3、背包放满时,总共有多少种方案?
完全背包问题:完全背包中,每件物品可以放无穷件。
一些优化:
1.若两件物品i、j满 足Ci ≤ Cj且Wi ≥ Wj,则将可以将物品j直接去掉,不用考虑。 的O(N2)
2.首先将费用大于V 的物品去掉,然后使 用类似计数排序的做法,计算出费用相同的物品中价值最高的是哪个,可 以O(V + N)地完成这个优化O(V + N)
主要代码:
内层循环恢复正序,这样更新d[v]的时候就可以算上多次加入自己的情况
for(int i=1;i<=N;++i) for(int v=Ci;v<=V;++v) d[v]=max(d[v],d[v-Ci]+Wi);
多重背包问题