背包问题总结

背包问题

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]);

分组背包

每组至多选一个物品

树上分组背包
posted @ 2019-11-07 11:19  陈星卿  阅读(270)  评论(0编辑  收藏  举报