luogu P3423 [POI2005]BAN-Bank Notes

Posted syhakioi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P3423 [POI2005]BAN-Bank Notes相关的知识,希望对你有一定的参考价值。

Byteotian Bit Bank (BBB) 拥有一套先进的货币系统,这个系统一共有n种面值的硬币,面值分别为b1, b2,…, bn. 但是每种硬币有数量限制ci,现在我们想要凑出面值k求最少要用多少个硬币.

n<=200,bi<=20000,ci<=20000

还要输出方案。。。。

 

这道题第一眼多重背包,然后打了 ,65分,开O2 70分。。

我们可以换个思路,何必枚举每种货币选多少个,每次只拿一个,只要记录一下前面状态拿了多少个,判断还有没有剩余就好了。

当然,第一维for循环不再是枚举货币,而是面值。

你要用单调队列,二进制拆分也没人拦你QAQ

Code

  

#include<iostream>
#include<cstdio>
#include<cstring>
#define R register
using namespace std;
int n,k,b[210],c[210],cnt[210][20010],f[20010],ans[210];
inline int read(){
    char c=getchar();int x=0,flag=1;
    while(c<0 || c>9){if(c==-) flag=-1;c=getchar();}
    while(c>=0 && c<=9) x=(x<<1)+(x<<3)+c-0,c=getchar();
    return x*flag;
}
int main(){
    n=read();
    for(R int i=1;i<=n;i++) b[i]=read();
    for(R int i=1;i<=n;i++) c[i]=read();
    k=read();
    memset(f,0x3f,sizeof(f));f[0]=0;
    for(R int i=1;i<=k;i++){
        int val=0; 
        for(R int j=1;j<=n;j++){
            if(i>=b[j]){
                if(f[i]>f[i-b[j]]+1 && cnt[j][i-b[j]]<c[j]){
                    f[i]=f[i-b[j]]+1;val=j;
                }
            }
        }
        cnt[val][i]=cnt[val][i-b[val]]+1;
        for(R int j=1;j<=n;j++) if(j!=val) cnt[j][i]=cnt[j][i-b[val]];
    }
    printf("%d
",f[k]);
    for(R int i=1;i<=n;i++) printf("%d ",cnt[i][k]);return 0;
}

 

以上是关于luogu P3423 [POI2005]BAN-Bank Notes的主要内容,如果未能解决你的问题,请参考以下文章

luogu 3423 [POI2005]BAN-Bank Notes

[Luogu3425][POI2005]KOS-Dicing

luogu P3420 [POI2005]SKA-Piggy Banks

Luogu 3421 [POI2005]SKO-Knights - Exgcd

[POI2005][luogu3462] SZA-Template [fail树]

[POI2005] SKA-Piggy Banks