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 }