首页 > 代码库 > UVA10313- Pay the Price
UVA10313- Pay the Price
题意:有关用硬币凑成所需面值的组合数。
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; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。