[POI2005]Bank notes 題解
阿新 • • 發佈:2020-08-08
【題目大意】
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 ; }