题目链接:Cash Machine
题意:分别给出N种货币的面值和数量,要求组合出不大于给定数额(cash)的最大的钱币总数。
输入:
每组数据一行,从左到右分别是:
要组合出的数额cash,钱币种类数n。以后每两数一组,分别代表钱币数量和面值。
解析:多重背包的变形,很巧妙的将常见的两种属性变成了一种,处理方法就是将每种货币的价值同时看成代价(因为总面值一定了,选定某种面值的货币,就代表要给出面值大小的代价),现在就是常见的多重背包问题了,我的解法是将每种货币拆分成1,2,3...2^(k - 1),D - 2^k + 1 (k是使D - 2^k + 1 > 0 的最大k)
种独立的货币,现在就可以用01背包的方法解决了。
代码:
#include <stdio.h>
#include <string.h>
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MAXN 10010
int D[MAXN];
int dp[MAXN*10];
int n,W;
void Init(){
int i;
int a,k,b;
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(i = 0;i < n;i ++){
scanf("%d%d",&a,&b);
k = 1;
while(k < a){
D[i ++] = k*b;
n ++;
a -= k;
k *= 2;
}
D[i] = a*b;
}
}
void DP(){
int i,j;
for(i = 0;i < n;i ++){
for(j = W;j >= 0;j --){
if(j - D[i] >= 0){
dp[j] = MAX(dp[j],dp[j - D[i]] + D[i]);
}
}
}
}
int main(){
while(scanf("%d",&W) != EOF){
Init();
DP();
printf("%d\n",dp[W]);
}
return 0;
}