[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 ;
}

posted @ 2020-08-08 18:36  hulean  阅读(309)  评论(0编辑  收藏  举报