dfs_选数问题

题意:
给定n个正整数,选择其中K个加起来等于S。问有多少种方法?
输入:
第一行,整数T< = 100,表示测试用例的数量。对于每种情况,都有两行。第一行,三个整数表示n,K和S。第二行,n 个整数表示这n个正整数。
输出:
对于每种情况,一个整数都处于独立的一行中表示答案。
输入样例:
输入样例
输出样例:
输出样例
解题思路:
这是一个经典的dfs回溯思想的题目,本质上是递归,从起点开始搜索目标,遇到障碍再折回上一节点。这里需要做一次剪枝操作,当选的数的个数超过K或者选的数的和超过sum时,这次搜索已经是注定失败的了,此时应当及时终止,体现在代码中就是递归的结束条件。if (num>k||sum>s)时就可以及时return了。否则在搜索到条件满足时对统计量ans递增,然后继续递归搜寻其他的方案。
注意事项:
1、无论是满足num>k||sum>s的条件还是num= =k&&sum= =s的条件,都需要及时return,因为两者一个代表搜索失败,一个代表搜索成功,均无需继续。
2、一般把需要的数组开在main外面,即静态区,这是一个常用的小技巧,根据题意开一个足够大的数组,而不是开在堆区或栈区。
总结:
数据结构课程着重讲了bfs遍历,dfs相对练习比较少。上一节课讲解的bfs算法相对比较固定一些,总体都是队列的操作,再加上不同维数的vis、dis数组等。这次的dfs算法感觉更灵活一些,练习的也比较少,可以用栈或递归的方式实现,但好像一般目前遇到的都更多采用递归的方式,递归的几个结束条件的设置尤其需要注意。
参考代码:

#include <iostream>
using namespace std;
int a[20];
int n,k,s;
int ans=0;
void dfs(int num,int sum,int position){
    if (num>k||sum>s) {
        return;
    }
    if (num==k&&sum==s) {
        ans++;
        return;
    }
    for (int j=position; j<n; j++) {
        dfs(num+1, sum+a[j], j+1);
    }
}
int main(int argc, const char * argv[]) {
    int t;cin>>t;
    while (t--) {
        ans=0;
        cin>>n>>k>>s;
        for (int i=0; i<n; i++) {
            cin>>a[i];
        }
        dfs(0,0,0);
        cout<<ans<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值