收银员现有 n 张面值分别为 v
的纸币。若找零金额为 m,则一共有多少种找零方法?
注:0<n≤1000,0<v
输入格式
输出格式
若有解,则输出全部找零方案,每输出一种 若无解,则输出“None”
输入样例1
6
3 1 4 3 2 7
9
结尾无空行
输出样例1
3 1 3 2
3 4 2
4 3 2
2 7
输入样例2
5
5 3 4 6 7
2
结尾无空行
输出样例2
None
知识点:回溯,剪枝。
思路:本题为子集问题,(即可以分为选与不选两种情况,不需要用个for循环,直接在dfs中写出两种情况,在此基础上进行剪枝)dfs(i,sum,op)(i为第i个元素,sum为选中的元素和,op是数组用来标记第i个元素选不选)
纠正:刚开始在dfs中用for循环进行遍历访问,其实不用,因为该题为子集问题不需要,for一般用于全排列
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int rm = 0;
int op[1005];
int v[1005];
int m;
int flag = 0;
void dfs(int i,int sum,int cnt) {
if (i>n) {
if (sum == m) {
flag = 1;
int j = cnt;
for (int k = 1;k <= n;k++) {
if (j == 1 && op[k] == 1) {
cout << v[k] << endl;
}
else if (op[k] == 1) {
cout << v[k] << " ";
j--;
}
}
}
return;
}
op[i] = 1;
if(sum + v[i]<=m)
dfs(i + 1, sum+v[i],cnt+1);
op[i] = 0;
dfs(i + 1, sum,cnt);
}
int main() {
cin >> n;
for (int i = 1;i <= n;i++) {
cin >> v[i];
rm += v[i];
}
cin >> m;
dfs(1,0,0);
if (flag == 0)
cout << "None" << endl;
}