p1036 选数(不详细勿看,递归)

题目:传送门

这题,不会做,而且看了好久才看懂题解的,然后在题解的基础上补了一个

if(start>end) return 0 感觉这样对于我更直观

转载自:大神博客的传送门,点击进入

先声明,我代码全部抄他的,原创是他

解释一下他的思路吧

就是比如说输入数字3 7 12 19,从中选三个

那么先要递归全排列再判断素数,主要是递归全排列难

他这里递归的直接就是答案的值,全部算完之后第一次调用函数的返回值就是答案

刚刚说到3 7 12 19

然后第一个可能选3或7或12或19这四种(这四种待会还会递归展开)

然后比如说第一次选了3,第二次就可能选7或12或19

比如说第一次选了12,第二次就可能选19,第三次时已经选了2次,还没到第三次,这时候再递归,start就会>end,就会return 0,通俗来说就是第二次选19本来就没意义,迟早要让他return 0,因为第二次选19,接下来就没得选了

如此一来就在没有重复的情况下完成了全排列那些全排列中畸形残缺的都被淘汰了

代码:

#include<iostream>
#include<math.h>
using namespace std;
int x[20],n,k;//依照题目所设
bool isprime(int n){//判断是否质数
    int s=sqrt(double(n));
    for(int i=2;i<=s;i++){
        if(n%i==0)return false;
    }
    return true;
}
int rule(int choose_left_num,int already_sum,int start,int end){//choose_left_num为剩余的k,already_sum为前面累加的和,start和end为全组合剩下数字的选取范围;调用递归生成全组合,在过程中逐渐把K个数相加,当选取的数个数为0时,直接返回前面的累加和是否为质数即可
    if(choose_left_num==0)return isprime(already_sum);
    if(start>end)return 0;//这一行是我自己加上去的
    int sum=0;
    for(int i=start;i<=end;i++){
        sum+=rule(choose_left_num-1,already_sum+x[i],i+1,end);
    }
    return sum;
}
int main(){
    cin>>n>>k;
    for(int i =0;i<n;i++)cin>>x[i];
    cout<<rule(k,0,0,n-1);//调用递归解决问题
}
原文地址:https://www.cnblogs.com/zyacmer/p/10088023.html