选数问题(dfs)

问题描述

Given n n positive numbers, ZJM can select exactly K K of them that sums to S S . Now ZJM wonders how many ways to get it!( n n 个数中选 K K 个数,其和等于 S S 的方案有多少个)

Input

The first line, an integer T 100 T\le 100 , indicates the number of test cases. For each case, there are two lines. The first line, three integers indicate n n , K K and S S . The second line, n n 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 16 k\le n\le 16 and all numbers can be stored in 32-bit integer

解题思路

\hspace{17pt} 这个题是一个典型的子集枚举问题,为了防止TLE,我们应该考虑一些特殊情况进行合理剪枝。
\hspace{17pt} 我们对这 n n 个数进行dfs,每个数有两种选择,取或者不取。那么我们就有了两种可行性剪枝方案: 1. 1. 选择数的个数大于 K K 2. 2. 已经选择数的总和大于 S S (由于所有数都是正数,大于 S S 就出现错误)。
\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;
}
发布了32 篇原创文章 · 获赞 24 · 访问量 2242

猜你喜欢

转载自blog.csdn.net/weixin_43347376/article/details/104677437