素数环
时间限制:1000 ms | 内存限制:65535 KB
难度:2
- 描写叙述
-
有一个整数n,把从1到n的数字无反复的排列成环,且使每相邻两个数(包含首尾)的和都为素数,称为素数环。
为了简便起见,我们规定每一个素数环都从1開始。比如,下图就是6的一个素数环。
- 输入
- 有多组測试数据,每组输入一个n(0<n<20),n=0表示输入结束。
- 输出
- 每组第一行输出相应的Case序号,从1開始。
假设存在满足题意叙述的素数环,从小到大输出。
否则输出No Answer。 - 例子输入
-
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
- 来源
- hdu改编
- 上传者
- ACM_丁国强
- 这道题应该算是比較简单的题了,提交了好几次都是TLE,我就郁闷了。。。看来基础还是不扎实啊。。。最后用素数的哈希表最终AC了。。。先前是各种TLE,程序优化真的非常重要啊。这就是算法的魅力所在~
#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(" "); } 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: ",k++); if(n==1)//自成环 { printf("1 "); continue; } if(n%2!=0)//剪枝,假设n为奇数不可能成环 { printf("No Answer "); 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!!!!