题意:
Given nn positive numbers, ZJM can select exactly KK of them that sums to SS. Now ZJM wonders how many ways to get it!
输入输出要求:
The first line, an integer T<=100T<=100, indicates the number of test cases. For each case, there are two lines. The first line, three integers indicate nn, Kand S. The second line, nn integers indicate the positive numbers.
For each case, an integer indicate the answer in a independent line.
样例输入:
1
10 3 10
1 2 3 4 5 6 7 8 9 10
样例输出:
4
数据范围:
Remember that k<=n<=16k<=n<=16 and all numbers can be stored in 32-bit integer
思路:
整体思路:
可以枚举所有子集判断是否合法 ,复杂度O(𝐾·2^𝑛)
剪枝:
枚举的子集里面有很多显然不可能合法的情况,直接跳过这些情况:
1)选的数的个数超过了K
2)选的数的和超过了S
递归:
递归结束的条件是:if(res_size=K && sum=0)
在这里,我用sum定义还可以再加的数值
总结:
这是一个搜索问题,为了避免暴力搜索,剪枝及其重要!!
代码:
#include<iostream>
using namespace std;
int m,n,K,S;
int count=0; //记录合法的组数
int res_size=0; //记录结果中数字个数
int a[16];
void solve(int i,int sum,int *a)
{
if(res_size==K&&sum==0) //递归结束的条件
{
count++;
return;
}
if(i>=n) return; //判断是否越界
if(res_size>K||sum<0) return; //可行性判断
solve(i+1,sum,a); //不选
res_size++;
solve(i+1,sum-a[i],a); //选
res_size--;
}
int main()
{
cin>>m;
while(m)
{
cin>>n>>K>>S;
for(int i=0;i<n;i++)
cin>>a[i];
solve(0,S,a);
cout<<count<<endl;
count=0;res_size=0;
m--;
}
return 0;
}