题目描述
母牛们不但创建了他们自己的政府而且选择了建立了自己的货币系统。
[In their own rebellious way],,他们对货币的数值感到好奇。
传统地,一个货币系统是由1,5,10,20 或 25,50, 和 100的单位面值组成的。
母牛想知道有多少种不同的方法来用货币系统中的货币来构造一个确定的数值。
举例来说, 使用一个货币系统 {1,2,5,10,…}产生 18单位面值的一些可能的方法是:18x1, 9x2, 8x2+2x1, 3x5+2+1,等等其它。
写一个程序来计算有多少种方法用给定的货币系统来构造一定数量的面值。
保证总数将会适合long long (C/C++) 和 Int64 (Free Pascal)。
输入
输入包含多组测试数据
货币系统中货币的种类数目是 V 。 (1<= V<=25)
要构造的数量钱是 N 。 (1<= N<=10,000)
第 1 行: 二整数, V 和 N
第 2 …V+1行: 可用的货币 V 个整数 (每行一个 每行没有其它的数)。
输出
单独的一行包含那个可能的构造的方案数。
样例输入
3 10
1 2 5
样例输出
10
递推公式还是不太熟悉,对完全背包的理解不够透彻,特别是当此题,
样例为 3 15 10 4 9 输出为0的时候,就不太懂这个原理了。
后期再对完全背包和背包问题的细节过程理一遍。
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
//属于完全背包,但是这题需要的是方案书,
//而不再数这个dp所能容纳的最大数目
//那么可以所见:两层for已经把所有情况都遍历了,
//从i1开始到全部容量, 状态公式即为dp 等于 选和不选的情况
//相加即可!
int main() {
long long N;
long long M;
while(scanf("%lld %lld",&N,&M)!=EOF&&N!=0&&M!=0) {
long long dp[10100] = {0};
long long a[10200];
dp[0] = 1;
for(int i =1; i <= N; i++)
scanf("%lld",&a[i]);
for(int i =1; i <= N; i++) {
for(int v = a[i]; v <= M; v++) {
dp[v] = dp[v] + dp[v-a[i]];
//加上i和不加上i的方案都算上去。
}
}
printf("%lld\n",dp[M]);
}
return 0;
}