Luogu P4095 [HEOI2013]Eden 的新背包问题 思维/动规

当时一直在想前缀和。。。多亏张队提醒。。。


 

从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\n",ans);
    }
}

2019.04.25

posted @ 2019-04-25 00:15  LuitaryiJack  阅读(162)  评论(0编辑  收藏  举报