Description
A ring is composed of n (even number) circles as shown in diagram. Put natural numbers into each circle separately, and the sum of numbers in two adjacent circles should be a prime.
Note: the number of first circle should always be 1.
Input
n (0 < n <= 16)
Output
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements.
You are to write a program that completes above process.
Sample Input
6 8
Sample Output
Case 1: 1 4 3 2 5 6 1 6 5 2 3 4 Case 2: 1 2 3 8 5 6 7 4 1 2 5 8 3 4 7 6 1 4 7 6 5 8 3 2 1 6 7 4 3 8 5 2
解题思路:如果这题用暴力枚举的话排列总数最高可高达16!=2*10^13,。就会超时。
所以这用回溯。用一个数组来储存要输出的序列,判断条件就是如果目前的数加上他前面的数的和为素数并且没有这数没被标记。满足条件就加1递归并标记。直到走到递归边界(cur==n)。
代码如下:
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 int vis[50],isp[50],A[50],n; 5 int is_prime(int x) //用一个函数来判断是不是素数 6 { 7 for (int i = 2; i*i<= x ; i++) 8 if (x% i == 0) return 0; 9 return 1; 10 } 11 12 void dfs(int cur) 13 { 14 if(cur==n&&isp[A[0]+A[n-1]]) //判断到递归边界没有,并且不要忘了判断最后一个和第一个加起来是不是素数,因为它是一个圆。 15 { 16 for(int i=0; i<n-1; i++) 17 printf("%d ", A[i]);//按照题目格式输出,注意空格问题。(我TM栽在这一上午) 18 printf("%d",A[n-1]); 19 printf(" "); 20 } 21 else 22 for(int i=2; i<=n; i++) //从2开始一个一个放 23 if(!vis[i]&&isp[i+A[cur-1]]) //如果满足条件,和没有被标记 24 { 25 A[cur]=i; 26 vis[i]=1; //标记 27 dfs(cur+1); //递归 28 vis[i]=0; //清除标记 29 } 30 } 31 int main() 32 { 33 int m=0; 34 while(scanf("%d",&n)==1&&n) 35 { 36 if(m>0) 37 printf(" "); 38 ++m; 39 for(int i=2; i<=n*2; i++) 40 isp[i]=is_prime(i); 41 printf("Case %d: ",m); 42 //memset(vis,0,sizeof(vis)); 43 A[0]=1; //A[0]一定为1 44 dfs(1); //从一开始递归 45 } 46 return 0; 47 }