488-素数环
内存限制:64MB 时间限制:1000ms 特判: No
题目描述:
有一个整数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
提示:
没有提示哦
来源:
hdu改编
上传者: ACM_丁国强
题目网址: http://nyoj.top/problem/488
题意: 本题要求给你一个大于0小于20的整数,然后你根据1到这个数中的所有整数来组合素数环,然后把所有符合条件的情况列举出来,若没有答案则输出No Answer。
思路: 这个题因为要一位一位来早符合条件的数,所以这个题可以用递归来写,也就是深搜dfs,要注意的是第一位都是1,搜索的时候每次要从2开始,然后找符合条件的数
代码:
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int n;
int a[20];
int flat;
int vis[20]={0}; //用来标记是否已经选过
int prime(int x) //判断素数
{
if(x<2)
return 0;
else
{
for(int i=2;i<=sqrt(x);i++) //到根号x即可
{
if(x%i==0)
return 0;
}
return 1;
}
}
void dfs(int x) //深搜
{
if(x==n&&prime(a[x-1]+1)==1) //找到符合条件的一组
{
flat=1; //标记是否能组合成素数环
for(int i=0;i<n;i++) //输出素数环
{
cout<<a[i];
if(i==n-1)
cout<<endl;
else
cout<<" ";
}
return ; //结束本次返回上一组
}
for(int i=2;i<=n;i++) //每次从2开始
{
if(vis[i]==0&&prime(a[x-1]+i)==1) //判断是否已经选过和这个数与前面已选好的数是否相加为一个素数
{
vis[i]=1; //标记已经选过
a[x]=i; //符合条件加到数组中
dfs(x+1); //深搜下一位符合条件的数
vis[i]=0; //解除标记
}
}
}
int main()
{
int d=0;
while(cin>>n)
{
if(n==0) //n为0结束
break;
flat=0; //初始标记为0
memset(vis,0,sizeof(vis)); //vis数组初始为0
a[0]=1; //以1开头
vis[1]=1; //标记
cout<<"Case "<<d+1<<":"<<endl;
if(n==1) //1时为1
cout<<"1"<<endl;
else if(n%2==1) //奇数时没有答案
cout<<"No Answer"<<endl;
else
{
dfs(1);
if(flat==0)
cout<<"No Answer"<<endl;
}
d++;
}
return 0;
}
运行结果:
总结: 深搜主要用到的是递归的思路,本题要注意的是除1外的奇数都不能组合成素数环,遇到奇数了就可以直接结束,节省时间。