标签:style blog http color 使用 os io for
题意:有关用硬币凑成所需面值的组合数。
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;
}UVA10313- Pay the Price,布布扣,bubuko.com
标签:style blog http color 使用 os io for
原文地址:http://blog.csdn.net/u011345461/article/details/38231275