1、问题描述:给定数组arr,arr中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个正数aim代表要找的钱数,求换钱有多少种方法?
2、问题来源:《算法与数据结构题目最优解》左程云 著
3、问题分析:这个问题和换钱的最少货币数相似,建议放在一起来研究。这个问题的关键在于前 i 种货币组成 j 的方案书为前 i-1 种组成 j 的方案数目 加上 前 i 种货币组成 j - arr[i] 的方案数目(需要注意此时 j > arr[i])。
4、以下是具体代码:
#include<iostream>
#include<vector>
using namespace std;
int main() {
int n, aim;//钱的面值的种类数和目标钱数
cin >> n >> aim;
int i, j;//辅助变量
vector<vector<int>> Num(n, vector<int>(aim + 1));//Num[i][j]代表用前0-i+1中货币组合成j的方案数目
vector<int> arr(n);
for (i = 0; i < n; ++i) {
cin >> arr[i];
}
//对Num[i][j]进行计算
for (i = 0; i < n; ++i) {
Num[i][0] = 1;//组合成钱数0的方案数目为1
}
for (j = 0; j < aim + 1; ++j) {
if (j%arr[0] == 0)
Num[0][j] = 1;//只使用arr[0]的时候需要是arr[0]的倍数
else
Num[0][j] = 0;
}
for (i = 1; i < n; ++i) {
for (j = 1; j < aim + 1; ++j) {
if (j < arr[i])
Num[i][j] = Num[i - 1][j];
else
Num[i][j] = Num[i - 1][j] + Num[i][j - arr[i]];
}
}
cout << "the Num is:" << Num[n - 1][aim] << endl;
}