poj1742(多重背包dp)

点击打开链接

/*
translation:
	给定一些硬币面额以及对应的个数,求用这些硬币可以拼凑成多少种不同数值的金额。
	
solution:
	多重背包dp
	这道题必须用多重背包dp的可行性类型O(nm)复杂度的算法来求解。
	设dp[i][j]:前i种拼凑出面值恰好为j时,最多还剩下几个第i种的硬币
	先将所有初始化为-1.则dp[i][j]>=0	dp[i+1][j] = c[i].
	j
#include 
#include 

using namespace std;
const int maxn = 105;
const int maxm = 100005;

int a[maxn], c[maxn];	//面值以及想对应的个数
int n, m;	//不同币值的种类数,最多不能超过多少钱
int dp[maxm];	//表示用前i种物品填满容量为j的背包后,最多还剩下几个第i中物品可以用

int main()
{
	//freopen("in.txt", "r", stdin);
    while(~scanf("%d%d", &n, &m) && n) {
		for(int i = 0; i < n; i++)	scanf("%d", &a[i]);
		for(int i = 0; i < n; i++)	scanf("%d", &c[i]);

		memset(dp, -1, sizeof(dp));
		dp[0] = 0;

		//实际实现过程用滚动数组来实现
		for(int i = 0; i < n; i++) {
			for(int j = 0; j <= m; j++) {
				if(dp[j] >= 0)	dp[j] = c[i];
				else if(j < a[i] || dp[j - a[i]] <= 0)
					dp[j] = -1;
				else	dp[j] = dp[j - a[i]] - 1;
			}
		}

		int cnt = 0;
		for(int i = 1; i <= m; i++)
			if(dp[i] >= 0)	cnt++;
		printf("%d\n", cnt);
    }
    return 0;
}


你可能感兴趣的:(=====动态规划=====,背包类dp)