[POI2005]BAN-Bank Notes

[POI2005]BAN-Bank Notes

POI真好玩。。
如果没有记录方案的话就是一个简单的二进制或单调队列优化多重背包的问题。
但是非常难受的是要记录方案。
而且空间只给了(64MB),,令人不适。。。
可以记录状态(to[i][j])表示从第i个物品转移到了j体积,这个在转移的时候记一下就行了
这个空间如果用二进制优化的话就需要(nlog_bk)的空间,大概是(200×14×20000=56000000)空间,必须开成(bool)数组,如果直接开(int)(MLE)

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=205,K=20005;
int n,a[N],f[K],b[N],tot,k,ans[N];
bool to[N<<4][K];
struct THINGS{
    int vol,val,id;
}t[N<<4];
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    for(int i=1;i<=n;i++) {
        for(int j=1;b[i]>=j;b[i]-=j,j<<=1) 
            t[++tot]=(THINGS){a[i]*j,j,i};
        if(b[i]) t[++tot]=(THINGS){a[i]*b[i],b[i],i};
    }
    scanf("%d",&k);
    memset(f,0x3f,sizeof f);
    f[0]=0;
    for(int i=1;i<=tot;i++) 
        for(int j=k;j>=t[i].vol;j--) 
            if(f[j]>f[j-t[i].vol]+t[i].val) to[i][j]=1,f[j]=f[j-t[i].vol]+t[i].val;
    printf("%d
",f[k]);
    int now=k,sum=f[k];
    for(int i=tot;sum;) {
        while(!to[i][now]) i--;
        now-=t[i].vol;
        ans[t[i].id]+=t[i].val;
        sum-=t[i--].val;
    }
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/sdfzhsz/p/9814706.html