当时一直在想前缀和。。。多亏张队提醒。。。
从1到n背次包,保存每一个状态下的价值,就是不要把第一维压掉;再从n到1背一次,同样记住每种状态;
然后询问时相当于是max(前缀+后缀),当然前缀后缀中间去掉了一个应去掉的商品。
#include<cstdio> #include<iostream> #define R register int using namespace std; inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } int n,q; int a[1010],b[1010],c[1010],f[1010][1010],h[1010][1010]; signed main() { n=g(); for(R i=1;i<=n;++i) a[i]=g(),b[i]=g(),c[i]=g(); for(R i=1;i<=n;++i) for(R j=1000;j>=0;--j) { f[i][j]=f[i-1][j]; for(R k=1;k<=c[i];++k) if(j>=k*a[i]) f[i][j]=max(f[i][j],f[i-1][j-k*a[i]]+k*b[i]); else break; } for(R i=n;i>=1;--i) for(R j=1000;j>=0;--j) { h[i][j]=h[i+1][j]; for(R k=1;k<=c[i];++k) if(j>=k*a[i]) h[i][j]=max(h[i][j],h[i+1][j-k*a[i]]+k*b[i]); else break; } q=g(); for(R i=1;i<=q;++i) { R k=g(),w=g(); R ans=0; for(R i=0;i<=w;++i) ans=max(ans,f[k][w-i]+h[k+2][i]); printf("%d ",ans); } }
2019.04.25