题解——洛谷P4095 [HEOI2013]Eden 的新背包问题(背包)

思路很妙的背包

用了一些前缀和的思想

去掉了一个物品,我们可以从前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\n",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\n",ans);
  }
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/dreagonm/p/9577915.html
今日推荐