码迷,mamicode.com
首页 > 其他好文 > 详细

luogu P3423 [POI2005]BAN-Bank Notes

时间:2019-10-14 12:42:53      阅读:104      评论:0      收藏:0      [点我收藏+]

标签:reg   pac   lag   byte   fine   getch   while   循环   思路   

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\n",f[k]);
    for(R int i=1;i<=n;i++) printf("%d ",cnt[i][k]);return 0;
}

 

luogu P3423 [POI2005]BAN-Bank Notes

标签:reg   pac   lag   byte   fine   getch   while   循环   思路   

原文地址:https://www.cnblogs.com/SyhAKIOI/p/11670768.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!