【多重背包小小的优化(。・∀・)ノ゙】BZOJ1531-[POI2005]Bank notes

【题目大意】

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

【思路】

裸的多重背包能过,不过好像有个神奇的优化?

把c[i]拆分成(1、2、4、……、2^x、余下数)的形式,由于每一次在前一次的基础上进行,可以拼凑初1..c[i]中的任意数。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MAXN=20000+50;
 7 const int INF=20000*200+5;
 8 int n,val,b[MAXN],c[MAXN];
 9 int f[MAXN];//凑出纸值x的面值数量 
10 
11 int main()
12 {
13     scanf("%d",&n);
14     for (int i=1;i<=n;i++) scanf("%d",&b[i]);
15     for (int i=1;i<=n;i++) scanf("%d",&c[i]);
16     scanf("%d",&val);
17     f[0]=0;
18     for (int i=1;i<=val;i++) f[i]=INF;
19     for (int i=1;i<=n;i++)
20         for (int k=1;c[i];k<<=1)
21         {
22             k=min(k,c[i]);
23             c[i]-=k;
24             for (int j=val;j>=k*b[i];j--)
25                 f[j]=min(f[j],f[j-k*b[i]]+k);
26         }
27     printf("%d",f[val]);
28     return 0;
29 }
原文地址:https://www.cnblogs.com/iiyiyi/p/5824715.html