题目描述
Byteotian Bit Bank (BBB) 拥有一套先进的货币系统,这个系统一共有
n
n
n 种面值的硬币,面值分别为
b
1
,
b
2
,
…
,
b
n
b_1,b_2,\dots ,b_n
b1,b2,…,bn。但是每种硬币有数量限制,现在我们想要凑出面值
k
k
k 求最少要用多少个硬币。
1
≤
n
≤
200
1\le n\le 200
1≤n≤200,
1
≤
b
1
<
b
2
<
⋯
<
b
n
≤
20
,
000
1\le b_1\lt b_2\lt\dots\lt b_n\le 20,000
1≤b1<b2<⋯<bn≤20,000,
1
≤
c
i
≤
20
,
000
1\le c_i\le 20,000
1≤ci≤20,000,
1
≤
k
≤
20
,
000
1\le k\le 20,000
1≤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;
}