Problem
给定n个正数,从中选出K个来使得他们的和为S,请问一共有多少种方法?
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, nn integers indicate the positive numbers.
Output
For each case, an integer indicate the answer in a independent line.
Example
Input
1 10 3 10 1 2 3 4 5 6 7 8 9 10
Output
4
解题思路:
数据结构:
题面很直观,只需要用到简单的数组即可。
算法:dfs
一、很容易想到的便是暴力枚举,即找集合的子集使得子集元素之和为给定值,复杂度为O(K·2^n)
二、再简单思考我们会发现
对于给定的元素有两种状态,要么选,要么不选,由于我们只选出k个即可,当选择了某个元素,问题就可以化解为求剩下的集合里面和为sum-该元素的k-1子集数目,一步一步递归下去、、、最后问题(可行)的终点为0个元素、和为0这样一个问题。//相当于组合问题的一个优化
Code:
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 5 int n,S,K,methods=0; 6 int *ar; 7 8 void dfs(int from,int sum,int num){ 9 if(sum<0||num<0) 10 return ; 11 12 if(num==0){ 13 if(sum==0){ 14 methods++; 15 return ; 16 } 17 else 18 return ; 19 } 20 else{ 21 for(int i=from+1;i<=n;i++) 22 dfs(i,sum-ar[i-1],num-1); 23 } 24 } 25 26 int main(){ 27 int T; 28 cin>>T; 29 cin>>n>>K>>S; 30 while(T--){ 31 ar = new int[n]; 32 for(int i=0;i<n;i++) 33 cin>>ar[i]; 34 sort(ar,ar+n); 35 dfs(0,S,K); 36 cout<<methods<<endl; 37 38 methods=0; 39 if(T==0) 40 //exit(0); 41 return 0; 42 43 cin>>n>>K>>S; 44 } 45 return 0; 46 }