A-选数问题
Description
给定n个正整数,选择他们其中的K个数总和是S,要求输入n,K,S,输出有多少种不同的选择。
Sample
input:
1
10 3 10
1 2 3 4 5 6 7 8 9 10
output:
4
Idea
首先我使用了list存放被选中的数,方便加入元素、去除元素,也可以时刻知道选中的个数。运用递归进行有选择的枚举,对于每个数来说,分别考虑选中它和不选它的情况,每加入一个元素就对sum减去相应的值,当list个数等于K并且sum恰好等于0时即是符合条件的一种解,而当list个数超过K或sum已经小于0时及时返回不再进行这种情况下的递归。
Summary
基本思想是枚举,进行全排列,依次判断每个子集是否满足要求。为了降低复杂度,要有选择地进行枚举,很多显然不成立的情况直接跳过,比如子集元素个数超过K、子集元素和超过S,当出现符合条件的解及时返回,因为再往下递归加入元素也必然不符合条件。
Codes
#include <iostream>
#include <list>
using namespace std;
int a[16];
int t,n, k, s;
int amount = 0;
void solve(int i,int sum,list<int> &res) {
if (res.size()==k&&sum == 0) { amount++; return; }
if (i >= n)return;
if (res.size()>k||sum < 0)return;
solve(i + 1, sum,res);
res.push_back(a[i]);
solve(i + 1, sum - a[i],res);
res.pop_back();
}
int main()
{
cin >> t;
while (t--)
{
amount = 0;
scanf("%d%d%d", &n, &k, &s);
memset(a, 0, sizeof(int));
for (int i = 0; i < n; i++)
cin >> a[i];
list<int> r;
solve(0, s, r);
printf("%d\n", amount);
}
}