有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环。
为了简便起见,我们规定每个素数环都从1开始。例如,下图就是6的一个素数环。
6 8 3 0
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 Case 3: No Answer
#include <stdio.h> #include <string.h> #define MAXN 40 int A[MAXN]; int vis[MAXN]; int n; int isprime[40]={ 0,0,1,1,0,1,0,1,0,0, 0,1,0,1,0,0,0,1,0,1, 0,0,0,1,0,0,0,0,0,1, 0,1,0,0,0,0,0,1,0,0, };//素数的哈希表,1代表就是素数 void dfs(int cur)//搜索+回溯(回溯其实也是根据树的深度搜索来的) { int i; if(cur==n && isprime[A[0]+A[n-1]])//递归边界,对第一个和最后一个数进行测试 { for(i=0;i<n;i++) printf("%d ",A[i]); printf("\n"); } else for(i=2;i<=n;i++)//尝试放置每一个数 if(!vis[i] && isprime[i+A[cur-1]])//先看这个数有没有被标记,然后看与前面的一个数的和是否为素数 { A[cur]=i; vis[i]=1;//标记搜索过的路径 dfs(cur+1); vis[i]=0;//清除标记 ,回溯 } } int main() { int i,j; int k=1; while(scanf("%d",&n)&&n!=0) { memset(vis,0,sizeof(vis));//初始化vis数组 for(i=0;i<n;i++) A[i]=i+1; printf("Case %d:\n",k++); if(n==1)//自成环 { printf("1\n"); continue; } if(n%2!=0)//剪枝,如果n为奇数不可能成环 { printf("No Answer\n"); continue; } dfs(1); } return 0; }
这里我应该还是钻了空子,还是不太严谨,20一类的偶数都能够成素数环,大于20就不一定了,还是有待改进啊。。
本来是想用筛选发筛选出素数的,各种TLE啊。。。 (感觉筛选法效率挺高的啊)
for(i=2;i<=MAXN;i++) { isprime[0]=isprime[1]=1; if(isprime[i]==0) for(j=i+i;j<MAXN ;j+=i) isprime[j]=1; }还是应该多学习别人的优秀算法,学无止境啊。 多学习别人的经验,keep moving!!!!
nyist 488 素数环(搜索+回溯),布布扣,bubuko.com
原文:http://blog.csdn.net/whjkm/article/details/24059129