nyoj 488 素数环

素数环

时间限制: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


#include<stdio.h>
#include<string.h>
#define MAX 22
int prime[110];//存放素数的数组 
int visit[MAX];//用来记录第i个数是否已经放置好位置即是否用过 
int a[MAX];    //储存并更新排序后的数的序列 
int cur;//因为代表当前所判断的数是第几个数 
int n; 
void biao()   //打表法将1到110之间所有素数用1标记放入数组中素数对应位置 
{             //其余数用0标记 
	int i,j,s;
	for(i=1;i<=110;i++)
	prime[i]=1;
	prime[1]=0;
	for(i=2;i<=110;i++)
	{
		if(prime[i]==1)
		{
			for(j=i*2;j<=110;j+=i)
			prime[j]=0;
		}
	}
} 
void dfs(int cur,int n)
{
	int i,j;
	if(cur==n+1&&prime[1+a[n]])  //如果当前判断的数是第n+1个数则证明前边所有的排序 
	{                             //均符合题意,因为是环所以要判断首尾相加是否为素数 
		for(i=1;i<=n;i++)
		printf("%d ",a[i]);
		printf("
");
		return ;
	}
	else
	{
		for(i=2;i<=n;i++)  //因为题目要求从1开始输出所以判断时从2开始回朔判断 
		{
			if(!visit[i]&&prime[i+a[cur-1]])//如果i没被用过并且i与他上一个的和为素数则往下执行 
			{
				a[cur]=i;   //将ichucun开始判断下一个数 
				visit[i]=1;//标记i已经用过 
				dfs(cur+1,n);//继续对下一个数进行判断 
				visit[i]=0;//清除标志 
			}
		}
		//return ;
	}
}
int main()
{
	int n,m,j,i,sum,k;
	biao();
	k=1;
	while(scanf("%d",&n)&&n!=0)
	{
		memset(visit,0,sizeof(visit));
		memset(a,0,sizeof(a));
		a[1]=1;visit[1]=1;
		printf("Case %d:
",k++);
		if(n&1)    //因为偶数偶数相加奇数奇数相加均不是素数所以素数环应该是奇数偶数间隔 
		{           //当n为奇数时无法达到素数偶数间隔所以判断n是否为素数 
			if(n==1)   //如果n是1则自己成环输出1 
			printf("1
");
			else    //否则输出No Answer 
			printf("No Answer
");
		}
		else
		dfs(2,n);
	}
	return 0;
}    
原文地址:https://www.cnblogs.com/tonghao/p/4554164.html