[POI2005]Bank notes 题解
【题目大意】
Byteotian Bit Bank (BBB) 拥有一套先进的货币系统,这个系统一共有\(n\)种面值的硬币,面值分别为\(b1, b2,..., bn\). 但是每种硬币有数量限制,现在我们想要凑出面值\(k\)求最少要用多少个硬币.
\(n\le200,1\le k,b_i \le100000\)
【分析】
看一眼题目,一道多重背包的模板题,但是数据范围比较大,如果直接写多重背包则会TLE
【优化】
考虑采用二进制进行优化
【代码】
#include <bits/stdc++.h>
using namespace std ;
const int MAXN = 1000000 + 5 ;
int n , k ;
int b[ MAXN ] ;
int f[ MAXN ] , w[ MAXN ] , c[ MAXN ] ;
inline void solve ( int wi , int ci , int numi ) { // 二进制拆分
int t = 1 ;
while ( numi >= t ) {
w[ ++ w[ 0 ] ] = wi * t ;
c[ ++ c[ 0 ] ] = t ;
numi -= t ;
t <<= 1 ;
}
w[ ++ w[ 0 ] ] = wi * numi ;
c[ ++ c[ 0 ] ] = numi ;
}
signed main () {
scanf ( "%d" , &n ) ;
for ( int i = 1 ; i <= n ; i ++ )
scanf ( "%d" , &b[ i ] ) ;
for ( int i = 1 ; i <= n ; i ++ ) {
int num ; scanf ( "%d" , &num ) ;
solve ( b[ i ] , 1 , num ) ;
}
memset ( f , 0x3f , sizeof ( f ) ) ; n = w[ 0 ] ;
scanf ( "%d" , &k ) ;
f[ 0 ] = 0 ;
for ( int i = 1 ; i <= n ; i ++ ) {
for ( int j = k ; j >= w[ i ] ; j -- ) {
f[ j ] = min ( f[ j ] , f[ j - w[ i ] ] + c[ i ] ) ;
}
}
printf ( "%d\n" , f[ k ] ) ;
return 0 ;
}