题意:给定货币面值种类(共V种,如1,2,5),求组成的总面值N(如10)的方法有多少种
解题思路:
- 依然是DP问题
- 用一维数组coins来存储各种面值,用二维数组f[i][j]来代表用前i种货币组成总面值j的方法种数
- 其中f[0][0] = 1
- f[i][j] = sum(f[i-1][k])其中 0<=k<=j,而且j-k能整除coins[i](也就是说j-k能只用第i种货币组成)
- f[V][N]即为所求
代码:
/*
ID: zc.rene1
LANG: C
PROG: money
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
FILE *fin, *fout;
int V, N, i, j, k;
int *coins = NULL;
long long **f = NULL;
fin = fopen("money.in", "r");
fout = fopen("money.out", "w");
fscanf(fin, "%d %d", &V, &N);
coins = (int*)malloc((V+1)*sizeof(int));
memset(coins, 0, (V+1)*sizeof(int));
for (i=1; i<=V; i++)
{
fscanf(fin, "%d", &coins[i]);
}
f = (long long**)malloc((V+1)*sizeof(long long*));
for (i=0; i<V+1; i++)
{
f[i] = (long long*)malloc((N+1)*sizeof(long long));
memset(f[i], 0, (N+1)*sizeof(long long));
}
f[0][0] = 1;
for (i=1; i<=V; i++)
{
for (j=0; j<=N; j++)
{
for (k=j; k>=0; k-=coins[i])
{
f[i][j] += f[i-1][k];
}
}
}
fprintf(fout, "%lld\n", f[V][N]);
return 0;
}