题目在 http://poj.org/problem?id=1276
题目大意是说,我现在要从ATM中取钱,M
ATM里面有若干种货币,每一种都有对应的货币面额和张数。
问现在ATM能够取出来的 小于等于M的最大金额。
若将M理解为背包重量,而每种货币的面额理解成 value,货币的面额同样理解成重量,那么这个问题就是一个多重背包问题。
多重背包问题可以转换成完全背包,使用一个used数据,used[k]的含义是:对于每一中货币 i, 达到金额 k 的时候,所使用的 面额是 i 的货币的个数。
对于循环体内的每个金额,我们要求达到这个金额所使用的货币数目要 小于等于给定的 这种货币的数量。
代码如下:
Source Code
Problem: 1276 User: hopeztm
Memory: 948K Time: 16MS
Language: C++ Result: Accepted
Source Code
#include <stdio.h>
#include <memory.h>
#define MAX_CASH 100001
struct Cash
{
int amount;
int demo;
};
int dp[MAX_CASH];
int used[MAX_CASH];
Cash allCash[11];
int nCash;
int nDeliver;
int maxCash()
{
if(nCash == 0 || nDeliver == 0)
return 0;
int i,j,k;
memset(dp, 0, sizeof(dp));
for( i = 1; i <= nCash; i++)
{
memset(used, 0, sizeof(used)); //使用used 数据来标记 used[j] 达到金额 j 的时候,所使用的 第 i 中钞票的个数
for( j = allCash[i].demo ; j <= nDeliver; j++)
{
if((dp[j] < dp[j - allCash[i].demo] + allCash[i].demo)
&& used[j - allCash[i].demo] + 1 <= allCash[i].amount) //要求到 金额j 的时候,所使用的 i 钞票个数小于等于给定的数目
{
dp[j] = dp[j - allCash[i].demo] + allCash[i].demo;
used[j] = used[j - allCash[i].demo] + 1;
}
}
}
return dp[nDeliver];
}
int main()
{
while(scanf("%d", &nDeliver) != EOF)
{
scanf("%d", &nCash);
for( int i = 1; i <= nCash; i++)
{
scanf("%d%d", &allCash[i].amount, &allCash[i].demo);
}
printf("%d\n", maxCash());
}
return 0;
}