思路很妙的背包
用了一些前缀和的思想
去掉了一个物品,我们可以从前i-1个和后i+1个推出答案
奇妙的思路
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; int f[2100][2100][2]={0},v[2100]={0},w[2100],num[2100],n,q,V; void zypack(int w,int v,int j,int wic){ if(wic==0) for(int i=V;i>=v;i--) f[j][i][wic]=max(f[j][i-v][wic]+w,f[j][i][wic]); else for(int i=V;i>=v;i--) f[j][i][wic]=max(f[j][i-v][wic]+w,f[j][i][wic]); } void wqpack(void){ for(int i=1;i<=n;i++){ for(int j=0;j<=V;++j) f[i][j][0]=f[i-1][j][0]; int rec=num[i]; int mid=1; while(mid<=num[i]){ zypack(w[i]*mid,v[i]*mid,i,0); num[i]-=mid; mid*=2; } zypack(w[i]*num[i],v[i]*num[i],i,0); num[i]=rec; } for(int i=n;i>=1;i--){ for(int j=0;j<=V;++j) f[i][j][1]=f[i+1][j][1]; int mid=1; int rec=num[i]; while(mid<=num[i]){ zypack(w[i]*mid,v[i]*mid,i,1); num[i]-=mid; mid*=2; } zypack(w[i]*num[i],v[i]*num[i],i,1); num[i]=rec; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d %d %d",&v[i],&w[i],&num[i]); } V=2000; scanf("%d",&q); wqpack(); // for(int i=1;i<=10;i++) // for(int j=1;j<=n;j++) // printf("f[%d][%d][0]=%d f[%d][%d][1]=%d ",j,i,f[j][i][0],j,i,f[j][i][1]); for(int i=1;i<=q;i++){ int x,y; scanf("%d %d",&x,&y); int ans=0; for(int j=0;j<=y;j++) ans=max(ans,f[x][j][0]+f[x+2][y-j][1]); printf("%d ",ans); } return 0; }