背包问题总结

背包问题

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)

  1. 二进制拆分
  2. 单调队列优化
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]);

分组背包

每组至多选一个物品

树上分组背包
原文地址:https://www.cnblogs.com/mzg1805/p/11810922.html