Uva674_Coin Change

题意:

用1、5、10、25、50 这五个面值的钱币去凑给定的金额n,问有多少种方案

思路:

定义状态: d(i, j)表示用前 i 种面值凑 j 共有多少种不同的方案
初始状态:
题目规定0金额有1种,d(1-5, 0) = 1;
前1中面值的凑法只有1种:d(1, 1-n) = 1;
状态转移:

  1. 当j < a[i], d(i, j) = d(i - 1, j - 1);
  2. 当j >= a[i],d(i, j) = d(i - 1, j)+ ∑ k = 1 j / a [ i ] \sum_{k=1}^{j/a[i]} k=1j/a[i]d(i - 1, j - k*a[i]);

先打表,不然超时

#include 
#include 
#include 
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int maxn = 7500;

int money[6] = {0, 1, 5, 10, 25, 50};

int d[6][maxn+1];
void dp(){
	for(int i = 0; i <= maxn; ++i) d[1][i] = 1;
	for(int i = 0; i <= 5; ++i) d[i][0] = 1;
	for(int i = 2; i <= 5; ++i){
		for(int j = 1; j <= maxn; ++j){
			if(j < money[i]) d[i][j] = d[i-1][j];
			else{
				d[i][j] = d[i-1][j];
				for(int k = 1; k <= j/money[i]; ++k){
					d[i][j] += d[i-1][j-k*money[i]];
				}
			}
		}
	}
}

int main()
{
	freopen("in.txt","r",stdin);
	dp();
	int n;
	while(scanf("%d",&n) == 1){
		//dp();
//		for(int i = 1; i <= 5; ++i){
//			for(int j = 1; j <= 26; ++j) printf("%d ", d[i][j]);
//			puts("");
//		}
		printf("%d\n", d[5][n]);
	}
	fclose(stdin);
	return 0;
}


你可能感兴趣的:(动态规划)