POJ 1276 多重背包问题

题目在 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 
#include 

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


你可能感兴趣的:(算法,C++)