题目488:素数环

来源:互联网 发布:php字符型转换函数 编辑:程序博客网 时间:2024/05/29 08:06

题目链接:

http://acm.nyist.net/JudgeOnline/problem.php?pid=488

描述

有一个整数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

算法思想:

深度搜索加减支法。考虑输入的数字个数为奇数时,由于奇数个数构成一个环,必有两个奇数会挨着,所有构成的环一定不是素数环。当输入的数的个数为偶数时,使用深度搜索遍历,当当前数与上一个数的和为素数时,则将该数标识为置为1,表示已经遍历过,且将其放入记录数组中,再以当前数作为参数进行递归遍历,遍历未成功,则回溯,将当前数的状态设为0。退出的条件是当记录数组的长度与输入数的个数相等且当且数与第一个数的和也为素数,此时退出。

最优代码

#include <stdio.h>#include <string.h>int n,ac[21]={1};bool in[21];bool is_prime(int x){    for(int i=2;i*i<=x;i++)        if(x%i==0)            return false;    return true;}//深度遍历void dfs(int cur){    //当记录数组的长度等于输入的长度时,退出    if(cur == n-1)    {        //如果记录数组的当前数与1(第一个数)的和为素数时,输出该素数环        if(is_prime(ac[cur]+1))        {            printf("1");            for(int i=1;i<n;i++)                printf(" %d",ac[i]);            printf("\n");        }        return ;    }    //循环遍历,查找未遍历(即未放入记录数组ac中)且与记录数组中当前值之和为素数的数,若查找到,则更新其状态    for(int i=2;i<=n;i++)    {        if(!in[i] && is_prime(i+ac[cur]))        {            in[i]=1;            ac[cur+1]=i;            dfs(cur+1);            in[i]=0;        }    }}int main(){    int ncase=0;    while(scanf("%d",&n),n)    {        printf("Case %d:\n",++ncase);        memset(in,0,sizeof(in));        if(n%2==0 || n==1)            dfs(0);        else  //n为奇数,减支法            printf("No Answer\n");    }    return 0;}        
原创粉丝点击