有一个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, 0, sizeof(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 ;
#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, 0, sizeof(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 ;
}