1. 程式人生 > >p1036 選數(不詳細勿看,遞歸)

p1036 選數(不詳細勿看,遞歸)

str 累加 als 四種 全部 判斷素數 end class ==

題目:傳送門

這題,不會做,而且看了好久才看懂題解的,然後在題解的基礎上補了一個

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);//調用遞歸解決問題 }

p1036 選數(不詳細勿看,遞歸)