主要思路:
使用递归解决
递归需要记录的信息:
- 当前选数的位置(从一个数组左端开始逐个选取)
- 已选的数的和
- 保存已选数的vector
在即将进入下一重递归时,有两种选择:将当前数字加入、不加入
若不进行剪枝,递归次数(复杂度)会高达 2n
可进行剪枝的地方:
- 当遍历的给定数组末尾时
- 当已选数字的个数超过要求时
- 当已选数字的和超过要求时
在以上三种情况出现时,即时停止即可
A - 选数问题
Given n positive numbers,
ZJM can select exactly K of them that sums to S.
Now ZJM wonders how many ways to get it!
Input
The first line, an integer T<=100, indicates the number of test cases.
For each case, there are two lines.
The first line, three integers indicate n, K and S.
The second line, n integers indicate the positive numbers.
Output
For each case, an integer indicate the answer in a independent line.
Sample Input
1
10 3 10
1 2 3 4 5 6 7 8 9 10
Sample Output
4
- A Possible Solution
#include<stdio.h>
#include<vector>
using namespace std;
int a[20], n, K, S, cnt;
vector<int> v;
void solution(int cur_num, int cur_sum, vector<int>& res) {
if (res.size() == K && cur_sum == S) {
cnt++;
return;
}
if (cur_num >= n)return;
if (v.size() > K || cur_sum > S)return;
solution(cur_num + 1, cur_sum, res);
res.push_back(a[cur_num]);
solution(cur_num + 1, cur_sum + a[cur_num], res);
res.pop_back();
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
cnt = 0;
scanf("%d %d %d", &n, &K, &S);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
solution(0, 0, v);
printf("%d\n",cnt);
}
return 0;
}