多重背包优化小结

普通多重背包

外层枚举哪个包,中层枚举容量,内存枚举数量

for(i=1; i<=n; ++i)
	for(j=m; j>=0; --j)
		for(k=1; k*w[i]<=j && j<=s[i]; ++k)
			f[j]=max(f[j], f[j-k*w[i]]+k*v[i]); 

二进制优化

相当于把每个包拆成 \(log\) 个包然后分别01背包

for(i=1; i<=n; ++i)
{
	cin>>v[i]>>w[i]>>s[i]; 
	for(j=1; j<=s[i]; j<<=1) 
		a[++k].v=v[i]*j, a[k].w=w[i]*j, s[i]-=j; 
	if(s[i]) a[++k].v=v[i]*s[i], a[k].w=w[i]*s[i]; 
}

for(...) //对a进行01背包

单调队列优化

相当于完全背包,但太久之前的要pop掉

for(i=1; i<=n; ++i)
{
	for(j=0; j<w[i]; ++j) l[j]=0, q[j][r[j]=1]=f[j], z[j][1]=0; 
	for(j=w[i]; j<=m; ++j)
	{
		while(l[j%w[i]]<r[j%w[i]] && j/w[i]-z[j%w[i]][l[j%w[i]]+1]>s[i]) ++l[j%w[i]]; 
		f[j]=max(f[j%w[i]], q[j][l[j]+1]+v[i]); 
		while((l[j%w[i]]<r[j%w[i]] && f[j]>q[j%w[i][r[j%w[i]]]])	--r[j%w[i]]; 
		q[j%w[i]][++r[j%w[i]]]=f[j]; z[j%w[i]][r[j%w[i]]]=j/w[i]; 
	}
}

没调过,不知道有没有打错

posted @ 2022-09-11 19:06  zhangtingxi  阅读(56)  评论(0编辑  收藏  举报