poj 1276 cash machine (多重背包)

有一个Cash Machine,里面装有t种面值为n[i]的货币,每种有v[i]张。问在所换金额不超过cash元钱的情况下,所能换取的最大金额。

多重背包,转换成01背包来做,其中要用到二进制优化。《背包九讲》上讲的挺不错,在每件物品价值前加上系数,并保证这些系数的组合包括1..n的所有数且总和为n。

代码:

#include<cstdio>
#include<cstring>
#define Max(a, b)   a>b?a:b
int dp[100005] ;
int val[105] ;
int main(){
    int cash, n, v, g, i, j, count ;
    while(~scanf("%d%d", &cash, &n)){
        if(!cash||!n){
            while(n--)
                scanf("%d%d", &g, &v) ;
            printf("0\n") ;
            continue ;
        }
        count = 0 ;
        memset(dp, 0sizeof(dp)) ;
        while(n--){
            scanf("%d%d", &g, &v) ;
            //二进制优化
            i = 1 ;
            while(g>=i){
                val[count++] = i * v ;
                g -= i ;
                i *= 2 ;
            }
            if(g)   val[count++] = v * g ;
        }
        //01背包求解
        for(i=0; i<count; i++){
            for(j=cash; j>=val[i]; j--){
                dp[j] = Max(dp[j], dp[j-val[i]]+val[i]) ;
            }
        }
        printf("%d\n", dp[cash]) ;
    }
    return 0 ;

} 

原文地址:https://www.cnblogs.com/xiaolongchase/p/2331538.html