题目:UVA - 10313Pay the Price(完全背包)
题目大意:同样是凑钱的问题,只是询问的时候是要按照凑钱用的硬币个数的范围来做统计的。
解题思路:这里零钱1--300,固定的。并且查询的N也是最大300,那么凑N最多的硬币个数就是N了,这里给定p,q说小于1100,所以只要大于300的就可以不用计算了,一定是0个。dp【i】【j】: 用j个硬币凑足i的种数。并且零钱是固定的,所以可以一开始就将1 -- 300的dp【N】【1..N]求出来,之后就直接查询。注意这里的N 可以等于0,要特判。
代码:
#include <cstdio>
#include <cstring>
const int N = 305;
typedef long long ll;
ll dp[N][N];
int Min (const int a, const int b) { return a < b ? a: b; }
void init () {
dp[0][0] = 1;
for (int i = 1; i <= 300; i++) {
for (int j = i; j <= 300; j++) {
for (int k = 0; k <= j - i; k++)
dp[j][k + 1] += dp[j - i][k];
}
}
}
int main () {
int n, l1, l2;
int x;
char ch;
init ();
while (scanf ("%d", &n) != EOF) {
scanf ("%c", &ch);
l1 = 0;
l2 = 300;
if (ch != '\n') {
scanf ("%d%c", &x, &ch);
if (ch != '\n') {
l1 = x;
scanf ("%d", &l2);
} else
l2 = x;
}
if (l1 <= 300) {
if (l2 > 300)
l2 = 300;
ll ans = 0;
for (int i = l1; i <= l2; i++)
ans += dp[n][i];
printf ("%lld\n", ans);
} else
printf ("0\n");
}
return 0;
}