Post

背包问题

多重背包

单调队列优化 复杂度:O(N^2)

看f[j]的转移 从 $f[j-v]+w,f[j-2\cdot v]+2\cdot w,f[j-3\cdot v]+3\cdot w$ …….中的最大值转移
j体积都会与相同的模数转移过来,考虑枚举从0~v-1的模数,体积每次加v,不同的模数转移互不影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const int M=200010;
int n,m;
int f[M],g[M],q[M];
void solve(){
	cin>>n>>m;//物品组数n,体积m
	for(int i=1;i<=n;i++){
		int c,w,s;
		cin>>c>>w>>s;//物品的体积,价值,个数
		memcpy(g,f,sizeof(f));
		for(int j=0;j<c;j++){
			int hh=0,tt=-1;
			for(int k=j;k<=m;k+=c){
				f[k]=g[k];
				if(hh<=tt&&k-c*s>q[hh])hh++;//当前队列里的个数为s个,需要弹出一个
				if(hh<=tt)f[k]=max(f[k],g[q[hh]]+(k-q[hh])/c*w);//从q[hh]到需要加上多少个w
				while(hh<=tt&&g[q[tt]]-(q[tt]-j)/c*w<=g[k]-(k-j)/c*w)tt--;//维护q[tt]>=k
				q[++tt]=k;
			}
  		}
	}
	cout<<f[m]<<'\n';
}
This post is licensed under CC BY 4.0 by the author.