题目描述:
输入正整数n,把整数1,2...n组成一个环,使得相邻两个数和为素数。输出时从整数1开始逆时针排列并且不能重复;
例样输入:
6
例样输出:
1 4 3 2 5 6
1 6 5 2 3 4
方法1:(生成测试法,会超时)
#include <bits/stdc++.h>
#define MAXN 100
using namespace std;
int isp[MAXN], a[MAXN];
void get_prime(void) //*****素数打表
{
memset(isp, 1, sizeof(isp));
isp[0]=isp[1]=0;
for(int i=2; i<MAXN; i++)
{
if(isp[i])
{
for(int j=2; j*i<MAXN; j++)
{
isp[i*j]=0;
}
}
}
}
int main(void)
{
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
get_prime();
int n;
cin >> n;
for(int i=0; i<n; i++)
{
a[i]=i+1;
}
do
{
int flag=1;
for(int i=0; i<n; i++) //****逐个尝试
{
if(!isp[a[i]+a[(i+1)%n]]) //****判断合法性
{
flag=0;
break;
}
}
if(flag) //****如果合法则输出序列
{
for(int i=0; i<n; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
}while(next_permutation(a+1, a+n)); //***1的位置不变
return 0;
}
方法2:(dfs+回溯)
代码:
#include <bits/stdc++.h>
#define MAXN 100
using namespace std;
int isp[MAXN], a[MAXN], vis[MAXN], n;
void get_prime(void) //****素数打表
{
memset(isp, 1, sizeof(isp));
isp[0]=isp[1]=0;
for(int i=2; i<MAXN; i++)
{
if(isp[i])
{
for(int j=2; i*j<MAXN; i++)
{
isp[i*j]=0;
}
}
}
}
void dfs(int cur)
{
if(cur==n && isp[a[0]+a[cur-1]]) //****递归边界
{
for(int i=0; i<n; i++) //***打印合法序列
cout << a[i] << " ";
cout << endl;
}
else
{
for(int i=0; i<n; i++) //***逐个尝试
{
if(!vis[i]&&isp[i+a[cur-1]]) //***i没用过且满足条件
{
a[cur]=i; //***存储当前序列
vis[i]=1; //****标记
dfs(cur+1); //***递归
vis[i]=0; //***去除标记
}
}
}
}
int main(void)
{
std::ios::sync_with_stdio(false),cin.fie(0),cout.fie(0);
get_prime();
cin >> n;
memset(vis, 0, sizeof(vis));
dfs(0);
return 0;
}