此题明显是一个回溯法
但是要注意的是,这道题也可以使用STL中呢next_permutation,来枚举所有的排列,然后一个一个判断
但是速度明显要比回溯法慢了很多。
还有一点就是素数的判断方式
下面附上AC代码:
//这道题我的想法就是枚举排列,第一位一定是1,然后又n-1步,每一步需要判断和前一位的和是不是素数,最后一位还需要和1判断一下 //另外还需要去判断一个数是不是素数 //判断是不是素数的方式有两种,第一种是每次都去判断,第二种是构造一个素数表,然后去判断,只需要构造到15+16即可 //构造素数表的方式就是从1开始去一个一个判断 //整体思路是正确的,但是在构造素数表的时候有出现了问题 //我之前想的素数表示存到set当中,然后每次去set中寻找 //但其实这样很慢,应该使用一个数组,数组中保存着当前下标是否为素数的标志 //下面来实现 #include<cstdio> #include<cstring> #include<ctime> using namespace std; const int maxn = 50; int vis[maxn]; int isp[maxn]; int n; int cnt = 0; int ans[maxn]; int is_prime(int x) { for(int i = 2;i * i <= x;i++) { if(x % i == 0) return 0; } return 1; } void DFS(int cur) { if(cur == n && isp[ans[cur - 1] + 1]) { for(int i = 0;i < n;i++) { if(i) printf(" "); printf("%d",ans[i]); } printf("\n"); } else { for(int i = 2;i <= n;i++) { if(!vis[i] && isp[i + ans[cur - 1]]) { vis[i] = 1; ans[cur] = i; DFS(cur + 1); vis[i] = 0; } } } } int main() { #ifdef local freopen("input.txt","r",stdin); freopen("out.txt","w",stdout); #endif while(scanf("%d",&n) == 1) { if(cnt) printf("\n"); printf("Case %d:\n",++cnt); for(int i = 2;i <= 2 * n;i++) { isp[i] = is_prime(i); } memset(vis,0,sizeof(vis)); ans[0] = 1; DFS(1); } return 0; }