把1~N(N<=20)个数摆成一个环,要求相邻两个数的和是素数。
环的第一个位置应该放1。
输出合法环的个数。
输入
输入一个整数
输出
输出环的个数
样例输入
6
样例输出
2
问题分析:首先我们不考虑其它问题,对于组成一个环来说,每组环共由N个数组成,对于每个数,又有N种可能。那么好了,我们自然而然的想到遍历所有的可能,找到符合要求,就能解决问题了。对,就是这样,这就是回溯法要解决的问题,但是你有没有想过,遍历完所有的可能,耗费的时间是很大的。这就意味着我们还要在回溯的基础上加一些东西,使得它更快的判断某组解符不符合要求,即剪枝。剪掉不符合的条件,从而寻求下一组解。
代码:
#include<bits/stdc++.h>
using namespace std;
int a[1000],c[1000];
int b[12]= {2,3,5,7,11,13,17,19,23,29,31,37};//列出素数的可能,可以有效缩短时间
int n;
int sum;
int check(int k)//剪枝,剪掉两数相加不是素数的情况
{
for(int i=0; i<12; i++)
{
if(k==b[i])
{
return 1;
}
}
return 0;
}
void hqs(int i)
{
int j;
if(i==n&&check(a[1]+a[i]))//环最后一个数和第一个数也要判断
{
sum++;
}
for(j=2; j<=n; j++)
{
if(check(a[i]+j)&&c[j]==0)
{
c[j]=1;//标记,使数不能重复
a[i+1]=j;
hqs(i+1);
c[j]=0;
}
}
}
int main()
{
while(cin>>n)
{
sum=0;
memset(c,0,sizeof(c));
a[1]=1;
hqs(1);
cout<<sum<<endl;
}
return 0;
}