题目描述
Byteotian Bit Bank (BBB) 拥有一套先进的货币系统,这个系统一共有 nnn 种面值的硬币,面值分别为 b1,b2,…,bnb_1,b_2,\dots ,b_nb1,b2,…,bn。但是每种硬币有数量限制,现在我们想要凑出面值 kkk 求最少要用多少个硬币。
1≤n≤2001\le n\le 2001≤n≤200,1≤b1<b2<⋯<bn≤20,0001\le b_1\lt b_2\lt\dots\lt b_n\le 20,0001≤b1<b2<⋯<bn≤20,000,1≤ci≤20,0001\le c_i\le 20,0001≤ci≤20,000,1≤k≤20,0001\le k\le 20,0001≤k≤20,000。
算法分析
多重背包裸题,使用二进制优化,输出方案和单调队列优化待填坑。
代码实现
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn=205;
const int maxk=20005;
int b[maxn],c[maxn],f[maxk];
int main() {
int n;scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&b[i]);
for(int i=1;i<=n;++i) scanf("%d",&c[i]);
int K;scanf("%d",&K);
memset(f,0x3f,sizeof(f));f[0]=0;
for(int i=1;i<=n;++i) {
for(int j=1;j<=c[i];j<<=1) {
for(int k=K;k>=b[i]*j;--k) f[k]=std::min(f[k],f[k-b[i]*j]+j);
c[i]-=j;
}
if(c[i]) for(int k=K;k>=b[i]*c[i];--k) f[k]=std::min(f[k],f[k-b[i]*c[i]]+c[i]);
}
printf("%d\n",f[K]);
return 0;
}