这题的数据比较厉害,如果不进行剪枝的话肯定会TLE的,剪枝:如果素数环元素的个数为奇数时一定是围成不了的,因为如果是奇数个元素,说明奇数的数字比偶数的数字1个,所以一定不可以形成奇偶相隔的情况,也就是说会出现两个奇数相邻,而奇数+奇数=偶数,不为素数。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
int n,casenum;
int isprime[50],prime[50],primesize,num[50];
bool vis[50];
bool flg;
void getlist(int listsize)
{
primesize=0;
memset(isprime,1,sizeof(isprime));
isprime[1]=false;
for(int i=2;i<=listsize;i++)
{
if(isprime[i])prime[++primesize]=i;
for(int j=1;j<=primesize&&i*prime[j]<=listsize;j++)
{
isprime[i*prime[j]]=false;
if(i%prime[j]==0)break;
}
}
}
bool dfs(int cur){
if(cur==n&&isprime[num[cur-1]+num[0]]){
for(int i=0;i<n;i++)
printf("%d%c",num[i],i==n-1?'\n':' ');
flg=true;
return true;
}
int j;
for(j=2;j<=n;j++){
if(!vis[j]&&isprime[num[cur-1]+j]){
vis[j]=true;
num[cur]=j;
dfs(cur+1);
vis[j]=false;///因爲下一次遞歸可以直接覆蓋掉下一個字符,所以不需要回復num數組
}
}
if(flg) return true;
return false;
}
int main(){
getlist(50);
casenum=0;
while(scanf("%d",&n)!=EOF){
if(n==0) break;
memset(num,0,sizeof(num));
t(vis,0,sizeof(vis));
flg=false;
vis[1]=true;
num[0]=1;
printf("Case %d:\n",++casenum);
if(n%2&&n>1){
printf("No Answer\n");
continue;
}
if(dfs(1));
else printf("No Answer\n");
}
return 0;
}