素數環問題---回溯
阿新 • • 發佈:2019-03-01
size pre argv 。。 color cstring ++ ons 結果
素數環
題目:輸入正整數n,把整數1。2,3,...,n組成一個環。使得相鄰兩個整數之和均為素數。
輸出時從整數1開始逆時針排列。
同一個環應該恰好輸出一次。n<=16
分析:首先運用普通方法(生成測試法)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int maxn =1e3; 8 int isp[maxn];9 int A[maxn]; 10 int n; 11 int ans=0; 12 13 int is_prime(int x){ 14 for( int i=2; i*i<=x; i++ ){ 15 if(x%i==0) return 0; 16 } 17 return 1; 18 } 19 20 int main(){ 21 cin>>n; 22 for( int i=2; i<=n*2; i++ ) isp[i]=is_prime(i);/*生成素數表,加快後續判斷*/ 23 for( int i=0; i<n; i++ ) A[i]=i+1; 24 do{ 25 int flag=1; 26 for(int i=0; i<n; i++ ){ 27 if(!isp[A[i]+A[(i+1)%n]]){/*不是素數,這種排列方式行不通*/ 28 flag=0; 29 break; 30 } 31 } 32 if(flag){ 33 ans++; 34for( int i=0; i<n; i++ ) cout<<A[i]<<" "; 35 cout<<endl; 36 } 37 }while(next_permutation(A+1,A+n));/*第一個位置是1!*/ 38 cout<<ans<<endl; 39 return 0; 40 }
這種方法當n=12就已經很慢了,n=16無法輸出結果。。。
思路二:回溯法。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 6 const int maxn =1000; 7 int vis[maxn]; 8 int A[maxn]; 9 int isp[maxn]; 10 int n; 11 int ans=0; 12 13 int is_prime(int x){ 14 for( int i=2; i*i<=x; i++ ){ 15 if(x%i==0) return 0; 16 } 17 return 1; 18 } 19 20 void dfs(int cur){ 21 if(cur==n&&isp[A[0]+A[n-1]]){ 22 ans++; 23 for( int i=0; i<n; i++ ) cout<<A[i]<<" "; 24 cout<<endl; 25 } 26 else{ 27 for(int i=2; i<=n; i++ ){ 28 if(!vis[i]&&isp[i+A[cur-1]]){/*i這個數沒被用過,並且符合前後兩個數相加為素數的要求*/ 29 A[cur]=i;/*采用這個數*/ 30 vis[i]=1;/*設置使用標誌*/ 31 dfs(cur+1); 32 vis[i]=0;/*消除標誌*//*回溯的本質*/ 33 } 34 } 35 } 36 } 37 int main(int argc, char const *argv[]) 38 { 39 cin>>n; 40 memset(vis,0,sizeof(vis)); 41 for( int i=2; i<=n*2; i++ ) isp[i]=is_prime(i); 42 A[0]=1;/*題目中規定從1開始*/ 43 dfs(1); 44 cout<<ans<<endl; 45 46 return 0; 47 }
素數環問題---回溯