多次背包 O(NV)

来源:互联网 发布:云计算技术与应用专业 编辑:程序博客网 时间:2024/06/10 17:13
用优先队列来优化能把多重背包的复杂度从O(NMV) 优化到O(NV)
#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int MaxN = 1000 + 5;int n,m,v[MaxN],gs[MaxN],que[MaxN<<1],lead,tail,last,now;double w[MaxN],f[2][MaxN<<1],add;char ch;void read(int &num){while(ch<'0'||ch>'9') ch=getchar();num=0;while(ch>='0'&&ch<='9') num=num*10+ch-'0',ch=getchar();}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) {scanf("%lf",&w[i]);read(v[i]);read(gs[i]);if(v[i]==0) add+=gs[i]*w[i];}for(int i=1;i<=n;i++){now=i&1;last=now^1;for(int j=0;j<=m;j++) f[now][j]=0;for(int j=0;j<v[i];j++){lead=1;tail=0;for(int k=j;k<=m;k+=v[i]){while(lead<=tail&&(k-que[lead])/v[i]>gs[i]) lead++;while(lead<=tail&&f[last][que[tail]]-((que[tail]-j)/v[i])*w[i]<f[last][k]-((k-j)/v[i])*w[i]) tail--;que[++tail]=k;f[now][k]=f[last][que[lead]]+((k-que[lead])/v[i])*w[i];}}}double maxn=f[n&1][0];for(int i=1;i<=m;i++) maxn=max(maxn,f[n&1][i]);printf("%.2lf",maxn+add);return 0;} 

0 0