1. 程式人生 > >【洛谷】P1036 選數

【洛谷】P1036 選數

洛谷P1036  選數

題目描述:

已知 n 個整數 x1,x2,…,xn,以及一個整數 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。

輸入輸出格式:

輸入輸出格式

輸入格式:

鍵盤輸入,格式為:

n , k (1<=n<=20,k<n)

x1,x2,…,xn (1<=xi<=5000000)

輸出格式:

螢幕輸出,格式為:

一個整數(滿足條件的種數)。

 

 我認為這是一道很適合做DFS入門題的水題

這道題說白了就是一道暴力

但如何暴力,怎樣的題該用暴力,這是不簡單的

這道題能很好得讓初學者認識到DFS並不僅僅侷限於棋盤(個人經驗)

 

演算法思路如下:

其實很簡單

暴力!暴力!暴力!

先確定第一個數,再向後列舉k-1個數

當累加到k個數時,判斷一下和是否為質數

接著,開始回溯

到前一個轉折點,再向後列舉“未走過的路”

當列舉到最後一個數時

轉折點提前,繼續列舉

 

若有更好見解,歡迎回復

 

以下程式碼僅供參考

#include<bits/stdc++.h>//萬能標頭檔案 
using namespace std;
int ans,n,k,a[50],i;
bool check(int a)//判斷質數(a即為選擇的k個數之和)
{
    int i;
    if(a<2) return false;
    for(i=2;i<=sqrt(a);i++)
    if(a%i==0) return false;
    return true;
}
void dfs(int num,int i,int sum)//(num表示已選數的個數,i表示下一個要列舉的數的位置,sum表示選數之和)
{ if(num==k)//當選了k個數時 { if(check(sum)) ++ans;//if所選數加起來是質數,ans累加 return; //回溯 } for(i;i<=n;i++)//只有這兩行才是核心程式碼(其實就是一個暴力,相當於n個數中列舉k個元素的集合) dfs(num+1,i+1,sum+a[i]);//以i向後列舉,由於前一步處理了邊界,這裡不需擔心會超過k個數 } int main() { cin>>n; cin>>k; for(i=1;i<=n;i++) cin>>a[i]; dfs(0,1,0);//(從0個數開始,下一步列舉第一個數,累加器暫時為0) cout<<ans;//完美輸出結果 return 0; }