【多重背包小小的优化(。・∀・)ノ゙】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 }