选数(深搜)

题目描述已知 n 个整数 x1,x2,…,xnx_1,x_2,…,x_nx1​,x2​,…,xn​,以及n个整数k(k<n)。从n个整数中任选k个整数相加,可分别得到一系列的和。例如当n=4,k=3,4个整数分别为3,7,12,19时,可得全部的组合与它们的和为:3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34现在,要求你计算出和为素数共有多少种。例如上例,只有一种的和为素数:3+7+19=29

这道题被放在递归的范围内,刚开始思路其实局限在根据k的大小写不同个循环枚举,后来觉得太麻烦;开始找其他方法,参考后发现题目所用方法叫深搜,简单了解后发觉大意就是就是先选第一个数字,按顺序推进
例如{1 2 3 4 5}从五个中选3个
首先把1选定,然后依次选出2,3 ,4,5,之后问题变为从四个中选两个
任然符合关系式
这种方法的关键在于选择一的时候会覆盖所有包含一的等式,所以按顺序选不会有重复在第一次选的时候就会遍历5个不合格的直接退出
在吧剩下的继续选按顺序选择从小到大可以有效避免重复的情况,如果第一个数选4凑不足三个无法找到函数出口,或者说类加入口
关于这个函数相关代码如下
t为和是素数的等式的个数

void dfs(int d, int count, int sum) {
    int i;
    if (count == k && prime(sum)) 
    t++;
    for (i = d; i <= n; i++) 
       dfs(i + 1, count + 1, sum + a[i]);
}   

prime函数为布鲁性返回值为1或0;
这个函数关键在于在一步步深入搜索的过程中没有重复情况
如果count不足k就不会影响最终结果t的变化;
第一次使用如果有不对也请多指正

下面放本题ac代码

#include <iostream>
using namespace std;
int n,k,t,a[20];
int prime(int a)
{int w=1;
 for(int i=2;i<a;i++)
 {
 if(a%i==0)
 w=0;
 return w;
}
void dfs(int d, int count, int sum) 
{ int i;
    if (count == k && prime(sum)) 
        t++;
    for (i = d; i <= n; i++) 
    dfs(i + 1, count + 1, sum + a[i]);
}   
int main()
{cin >> n >> k;
    for ( int i = 1; i <= n; i++) {
        cin >> a[i];
    } dfs(1, 0, 0);
cout<<t;
 return 0;
}
发布了20 篇原创文章 · 获赞 17 · 访问量 1012

猜你喜欢

转载自blog.csdn.net/weixin_45757507/article/details/103286255