多重背包单调队列优化

/*后来该数据了那个题 原来的被卡常数了 重写了一份*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 7010
#define mem(a,b)for(int i=0;i<=m;i++)a[i]=b[i]
#define mes(a,b)for(int i=0;i<=m;i++)a[i]=b
using namespace std;
int n,m,f[maxn],g[maxn],q[maxn],p[maxn],head,tail;
int init(){
    int x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
void Pack(int w,int v,int c){
    if(w>m)return;
    mes(g,0);
    for(int i=0;i<w;i++){
        head=1;tail=0;g[i]=f[i];
        q[++tail]=i;p[tail]=f[i];
        for(int t=v,j=w+i;j<=m;j+=w,t+=v){
            while(head<=tail&&p[tail]<=f[j]-t)tail--;
            tail++;q[tail]=j;p[tail]=f[j]-t;
            if((j-q[head])/w>c)head++;
            g[j]=p[head]+t;
        }
    }
    mem(f,g);
}
int main()
{
    n=init();m=init();
    int w,v,c;
    for(int i=1;i<=n;i++){
        w=init();v=init();c=init();
        Pack(w,v,c);
    }
    printf("%d
",f[m]);
    return 0;
}
原文地址:https://www.cnblogs.com/yanlifneg/p/5966240.html