背包问题
0/1背包
有(n)个物品,每个物品有一个体积(v),价值(w),每个物品只能选一次,问在所选体积不超过(m)的情况下的最大价值
枚举每个物品选或不选
设(f[i,j])表示前(i)件物品,选的体积不超过(j)的最大价值
-
初始化 (f[0,[0,m]] = 0)
-
转移
[f[i,j] = max(f[i-1,j],f[i-1,j-v_i]+w_i)
]
- 目标 (f[n,m])
倒序循环(j)可滚动数组优化空间
注意:如果(f[i,j])的定义是选的体积等于(j)的最大价值,那么
- 初始化 (f[0,[1,m]] = inf,f[0,0] = 0)
- 目标 (max{f[n,i]},0 leq i leq m)
如果题目要求等于(m)就只能用第二种定义,相应的目标就为(f[n,m])
完全背包
每个物品可选无数次
滚动并正序循环(j)即可
注意的地方同上
多重背包
每个物品有(c)个
- 二进制拆分
- 单调队列优化
for(in(n),in(m),i = 1;i <= n; ++i) {
for(in(w),in(v),in(c),j = 0;j < v; ++j) {
l = 1,r = 0,lim = (m-j)/v;
for(k = 0;k <= lim; ++k) {
while(l <= r && q[r].v <= f[k*v+j]-k*w) --r;
q[++r] = qwq {k,f[k*v+j]-k*w};
while(l <= r && q[l].pos < k-c) ++l;
if(l <= r) f[k*v+j] = q[l].v+k*w;
}
}
}
out(f[m]);
分组背包
每组至多选一个物品