题意:给定一个整数,求其满足起点为1的素数环,,并把所有的素数环输出来。
类型:dfs+回溯
思路:因为起点为1,所以每次都从1开始进行深度优先搜索,设置一个数组ring,用来存放素数环的路径,当找到素数环的时候就打印环的路径。其中有一个剪枝的操作,如果给定的整数为奇数,那么肯定不存在素数环,(因为肯定存在两个奇数相邻,而奇数与奇数的和为偶数,所以一定不是素数环)所以不用进行搜索。做题的时候忘记写输入的数据以EOF结束,导致出现了Output Limit Exceeded这种错误。
#include<iostream> #include<cstdio> #include<algorithm> #include<stdlib.h> #include<string.h> #define N 50 using namespace std; int visit[N];//标记整数是否被访问 int ring[N];//用来存放满足素数环的整数 int n;//素数环的大小 bool isprime(int k)//判断是否为素数,由于题目给定的范围很小,所以可以用这种直接的方法判断,不会超时 { bool tag; tag=true; if(k==2) return tag; for(int j=2; j*j<=k; j++) { if(k%j==0) { tag=false; break; } } return tag; } void dfs(int l) { if(l==n&&isprime(ring[l]+ring[1]))//最后一次,跳出递归,输出素数环 { for(int i=1;i<n;i++) printf("%d ",ring[i]); printf("%d\n",ring[n]); return; } for(int j=2; j<=n; j++)//因为题目要求打印的素数环要按照字典序排列,所以从小到大遍历整数 if(!visit[j]&&isprime(ring[l]+j))//未被访问过,并且满足与上一次记录的整数之和为素数 { visit[j]=1;//标记该整数已被访问 ring[l+1]=j;//更改记录整数,用作下一次素数环的判断 dfs(l+1);//递归实现,参数表示已经找到的满足素数环的整数的个数 visit[j]=0;//回溯,因为下一次可能要用到该整数。 } } int main() { int cased=1; while(scanf("%d",&n)!=EOF) { memset(ring,0,sizeof(ring));//置0 memset(visit,0,sizeof(visit));//初始化为0 ring[1]=1;//第一个整数为1 printf("Case %d:\n",cased++); if(n%2==0&&n>0)//剪枝,如果为奇数肯定没有素数环,只有偶数才可能有素数环 dfs(1); printf("\n"); } return 0; }