1. 题意
给定n个正整数,要求选出k个数,使得选出来的k个数的和为s,输出方案的种数。
2.样例
Sample Input
第一行输入数据组数
第二行输入n,k,s
第三行输入n个正整数
Sample Output
输出方案数目
3.解题思路
分析:
1.这是一个典型的子集枚举问题,可以列举所有子集判定是否合法,但复杂度高。
2.进行优化,即可行性剪枝,排除一些不合法的情况减少枚举次数,即排除选的数目超过了k,选的数的总和超过了sum。
4.总结
1.对于此类题目,我们要考虑怎样将数据进行优化,进行可行性剪枝或优化剪枝
2.对于本题,我采用vector进行存储数据,所以每进行一组数据后要将vector清空处理
3.对于此题枚举,很像枚举中的位向量法,对于每个子集,两种状态要么选中,要么没选中,枚举每一个位置的状态,可以得到各种子集
void s(int i,vector<int> &res)
{
if(i==n)
{
for(int i=0;i<res.size();i++)
{
cout<<res[i]<<" "
}
cout<<endl;
return;
}
s(i+1,res);
res.push_back(v[i]);
s(i+1,res);
res.pop_back();
}
5.AC代码
#include<iostream>
#include<vector>
using namespace std;
int n,k,count=0,sum;
vector<int> v;
void dfs(int i,int sum,vector<int> &res)
{
if(res.size()==k&&sum==0)
{
count++;
return ;
}
if(i>=n||res.size()>k||sum<0) return;
dfs(i+1,sum,res);
res.push_back(v[i]);
dfs(i+1,sum-v[i],res);
res.pop_back();
}
int main()
{
int m,k2;
cin>>k2;
for(int j=0;j<k2;j++)
{
vector<int>v1;
cin>>n>>k>>sum;
for(int i=0;i<n;i++)
{
cin>>m;
v.push_back(m);
}
dfs(0,sum,v1);
cout<<count<<endl;
while(v.size()!=0)
{
v.pop_back();
}
count=0;
}
return 0;
}