UVA10313- Pay the Price

来源:互联网 发布:c语言不等于 编辑:程序博客网 时间:2024/04/30 22:19

题意:有关用硬币凑成所需面值的组合数。

1、只有N,表示使用个数从1 - N的硬币凑成面值为N的组合数

2、N,L1,表示使用个数从1 - L1的硬币凑成面值为N的组合数

3、N,L1,L2,表示用个数从L1 - L2的硬币凑成面值为N的组合数


思路:这题用到了Ferrers图像的性质,即将整数N拆分成不超过n个数之和的拆分数的方案数与将整数N拆分成若干数但都不大于n的方案数是相同的。

对于这到题目就可以这样转换,用不超过j个硬币构成面值为i的方案数等于用不超过j面值的硬币构成面值为i的方案数相同。

所以d[i][j]表示用不超过j面值的硬币构成面值为i。当选择了j面值的硬币构造i的方案数为d[i - j][j],不选择的话为d[i][j - 1];


状态转移方程:d[i][j] = d[i - j][j] + d[i][j - 1]


有关Ferrers图像的性质:Ferrers图像性质


#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 305;const int N = 300;char s[MAXN];int n, l1, l2;long long sum, d[MAXN][MAXN]; void dp() {    memset(d, 0, sizeof(d));     d[0][0] = 1;    for (int i = 0; i <= N; i++)         for (int j = 1; j <= N; j++) {            if (i >= j)                   d[i][j] = d[i - j][j] + d[i][j - 1];            else                d[i][j] = d[i][j - 1];             }}int main() {    dp();    while (gets(s) != NULL) {        int num = sscanf(s, "%d %d %d", &n, &l1, &l2);         l1 = l1 > N ? N : l1;        l2 = l2 > N ? N : l2;        sum = 0;        if (num == 1)             sum = d[n][n];          else if (num == 2)             sum = d[n][l1];          else            sum = d[n][l2] - d[n][l1 - 1];         printf("%lld\n", sum);    }    return 0;}


0 0
原创粉丝点击