素数环(DFS)

素数环

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

 

   思路:

   回溯法(DFS)。如果给出数为奇数,则必有其中两个奇数相邻,那么相加则为偶数,所以n为奇数时,输出No Answer。而当n为偶数时,必然会存在符合素数环的序列。当n等于1时,也能输出,这时候1形成自环。

 

   AC:

#include<stdio.h>
#include<string.h>
int prime[40];  //考虑最大相邻相加数的情况,18+19=37,所以把边界定为40
int vis[20],pos[20];
//vis登记当前数是否已经访问,pos为序列的位置
void DFS(int k,int n)
{
	if(k==n+1&&prime[pos[1]+pos[n]])   //判断退出的条件
//注意不要忘了判断最后一个和第一个相加是否为素数
	{
		for(int j=1;j<=n;j++)
			{
			 printf("%d",pos[j]);
			 j==n?printf("\n"):printf(" ");
			}
		return;
	}
	else
	{
		for(int i=2;i<=n;i++)
		{
			if(!vis[i]&&prime[i+pos[k-1]]) 
//这里是k-1,因为是逐个向后添加的,所以应该是判断添加的数和上一个数的和是否为素数
//未访问,且这个数与上一个数相加和为素数
			{
			 vis[i]=1;
			 pos[k]=i;
			 DFS(k+1,n);
			 vis[i]=0;
//记住要清楚标记
			}
		}
	}
}

int main()
{
	int n,times=1;
	memset(prime,0,sizeof(prime));
	prime[2]=1,prime[3]=1,prime[5]=1,prime[7]=1,prime[11]=1,prime[13]=1;
	prime[17]=1,prime[19]=1,prime[23]=1,prime[29]=1,prime[31]=1,prime[37]=1;
//素数表
	while(scanf("%d",&n)!=EOF&&n)
	{
		printf("Case %d:\n",times++);
		if(n==1) printf("1\n");
		else
		{
		  if(n%2)  printf("No Answer\n");
		  else
		  {
			pos[1]=vis[1]=1;
			memset(vis,0,sizeof(vis));
			DFS(2,n);
		  } 
		}
	}
	return 0;
}

 

    总结:

    1.理解递归,弄清整个循环的过程;

    2.一开始先可以将n分为奇数和偶数的情况;

    3.输出的结果不一定只有一种,只要满足条件就能输出来。

 

    回溯法

    定义:

    回溯法也称试探法,它的基本思想是:从问题的某一种状态(初始状态)出发,搜索从这种状态出发所能达到的所有“状态”,当一条路走到“尽头”的时候(不能再前进),再后退一步或若干步,从另一种可能“状态”出发,继续搜索,直到所有的“路径”(状态)都试探过。这种不断“前进”、不断“回溯”寻找解的方法,就称作“回溯法”。

 

    基本思想:

    在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。

 

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值