c++演算法之回溯 素數環(二)
阿新 • • 發佈:2019-01-25
Description
輸入正整數n,把整數1,2,3,…,n組成一個環,使得相鄰兩個整數之和均為素數。把全部的解按字典序排序後,從1開始編號,依次輸出指定編號的k組解。最後一行輸出總的方案數。同一個素數環只算一次。
Input
第1行:2個整數,n(n<=18)和k(1<=k<=10)
第2行:共有k個從小到大排列的整數,表示要輸出的解的編號。
Output
前k行,每行一組解,對應於一個輸入
第k+1行:一個整數,表示總的方案數。
Sample Input
10 4
1 2 5 8
Sample Output
1 2 3 4 7 6 5 8 9 10 1 2 3 4 7 10 9 8 5 6 1 2 3 8 5 6 7 10 9 4 1 2 3 10 9 8 5 6 7 4 96
分析:
演算法思維與(一)一樣,但需要注意這樣兩點(坑點):
1.“把全部的解按字典序排序後,從1開始編號,依次輸出指定編號的k組解。最後一行輸出總的方案數。同一個素數環只算一次。”實現這句話其實就是要固定環的第一個數為1,這樣就可以保證不重複,且按字典序排序。
2.要求輸出指定的k組解,我是在輸出的時候處理的,要統計總數就在那裡自增,再判斷當前解是否是指定的k組解中的,是才輸出
程式實現如下:
#include<cstdio> #include<cmath> int a[19],k,sum,n[11],num=1,q; bool b[19]={0}; bool p(int s)//判斷是否為素數 { for(int i=2;i<=sqrt(s);i++) if(s%i==0) return 0; return 1; } void print() { sum++;//此時的sum也是此素數環的順序,產生完所有的素數環之後,sum即為所有的組數 if(sum==n[num])//如果此時是k組資料,才輸出 { for(int i=1;i<q;i++) printf("%d ",a[i]); printf("%d\n",a[q]); num++;//num滾動遞增到下一個要求的素數環的序號 } } int search(int r) { for(int i=2;i<=q;i++) if(!b[i]&&p(i+a[r-1]))//沒有被使用過,且與前一個數相加是素數 { a[r]=i; b[i]=1;//儲存並標記 if(r==q&&p(1+a[q])) print();//如果填完所有的數,且最後一個數與開頭的數之和為素數 else search(r+1);//遞歸回溯 b[i]=0; } } int main() { scanf("%d %d",&q,&k); for(int i=1;i<=k;i++) scanf("%d",&n[i]);//將k組資料儲存在n陣列中 a[1]=1; b[1]=1;//將第一個數固定為1,從2開始搜尋 search(2); printf("%d",sum);//最後輸出總數 }