问题描述
Given nnn positive numbers, ZJM can select exactly KKK of them that sums to SSS. Now ZJM wonders how many ways to get it!(nnn个数中选KKK个数,其和等于SSS的方案有多少个)
Input
The first line, an integer T≤100T\le 100T≤100, indicates the number of test cases. For each case, there are two lines. The first line, three integers indicate nnn, KKK and SSS. The second line, nnn 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 Input
4
Note
Remember that k≤n≤16k\le n\le 16k≤n≤16 and all numbers can be stored in 32-bit integer
解题思路
\hspace{17pt}这个题是一个典型的子集枚举问题,为了防止TLE,我们应该考虑一些特殊情况进行合理剪枝。
\hspace{17pt}我们对这nnn个数进行dfs,每个数有两种选择,取或者不取。那么我们就有了两种可行性剪枝方案:1.1.1.选择数的个数大于KKK 。2.2.2.已经选择数的总和大于SSS(由于所有数都是正数,大于SSS就出现错误)。
\hspace{17pt}在下面的代码中使用list是为了方便调试,可以查看合法方案,单对此题来说,并没有使用list的必要,再开一个参数记录已经选择的个数即可。
完整代码
//#pragma GCC optimize(2)//比赛禁止使用!
//#pragma G++ optimize(2)
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <list>
using namespace std;
const int maxn=20;
int T,n,k,s,ans,a[maxn];
list<int> l;//使用list就是为了查看当前有那些值
void dfs(int step,int sum)//step代表当前到了第几个数,sum是目前list中数的和
{
if (sum == s && l.size() == k){
ans++;
//for(auto it:l) cout<<it<<' ';//查看组成情况
//cout<<endl;
return;
}//当达到s并且数字个数达到k
if(step>n || l.size()>=k || sum>=s) return;//搜过了(此处注意应该是'>'号),个数大于k了,总和大于sum了,则返回
dfs(step+1,sum);//不取当前数,向后搜索
l.push_back(a[step]);//将当前数加入list中
dfs(step+1,sum+a[step]);//取当前数,向后搜索
l.pop_back();//将取的数弹出
}
int getint()
{
int x=0,s=1;
char ch=' ';
while(ch<'0' || ch>'9')
{
ch=getchar();
if(ch=='-') s=-1;
}
while(ch>='0' && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*s;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>T;
while(T--){
cin>>n>>k>>s;
ans=0; memset(a,0,sizeof(a));l.clear();
for (int i=1; i<=n; i++)
cin>>a[i];
dfs(1,0);
cout<<ans<<endl;
}
return 0;
}