[POI2005]BAN-Bank Notes
阅读原文时间:2023年07月10日阅读:1

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

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章