前面写的二进制优化多重背包可以把复杂度降到O(m*∑log k[i])
而接下来要说的单调队列优化可以把复杂度降到O(n*m);
我们知道,单调队列优化的条件是dp方程可以转移成如下形式
dp[i]=max/min(f[k])+g[i] (k<i 且g[i]与k无关)
而在多重背包中,如果把当前体积m分成v组(0,1,2,3,……v-1)就可以得到方程f[i*v+x]=f[k*v+x]+(i-k)*w;
即dp[i]=dp[k]+(i-k)*w;
dp[i]=dp[k]-k*w+i*w;
显然可以使用单调队列来进行优化
下面是代码实现
scanf("%d%d",&n,&m);//物品数,包体积
for(i=0;i<n;i++){
scanf("%d%d%d",&v,&w,&num);//当前物品的参数
if(m/c<num)//小优化,防止溢出而进行多余的运算
num=m/c;
for(k=0;k<v;k++){
head=tail=0;
for(j=0;j<(m-k)/c;j++){
int x=j;
int y=f[j*v+k]-j*w;
while(head<tail && y>=b[tail-1])
tail--;
a[tail]=x;//下标
b[tail++]=y;//值
while(a[head]<j-num)
head++;
f[j*v+k]=b[head]+j*w;
}
}
}