问题
从1~20一共20个数摆成一个环,要求相邻两个数的和是一个素数。输出一个合法答案。
输入样例:无
输出样例:一行,20个数,表示一个合法解。
分析
我们可以用穷举的方法输入数。
首先,相邻两个数是质数,我们就需要有判断质数的函数:
bool zs(int x){//判断质数
if(x==1)return 0;
for(int i=2;i<=sqrt(x);i++){
if(x%i==0)return 0;
}
return 1;
}
其中为了防止数字重复,我们需要运用剪枝算法。
接下来就是输入数的代码:
void dfs(int k){//k是第 k个数字
for(int i=1;i<=20;i++){
if(f[i]==0&&(k==1||zs(i+a[k-1]))){//判断数是否已被占用
a[k]=i;f[i]=1;//标记数被占用
if(k==20&&zs(a[k]+a[1]))print();//20个数已满且首尾相加为素数输出
else dfs(k+1);
f[i]=0;//恢复数
}
}
}
最后,需要补充输出函数:(要注意的是,因为只需输出一次,所以输出以后就要结束程序,防止重复。血的教训)
void print(){//输出函数
for(int i=1;i<=20;i++){
cout<<a[i]<<" ";
}
exit(0);
}
代码
#include<bits/stdc++.h>//素数环
using namespace std;
int a[25],cnt;
bool f[25];
void print(){//输出函数
for(int i=1;i<=20;i++){
cout<<a[i]<<" ";
}
}
bool zs(int x){//判断质数
if(x==1)return 0;
for(int i=2;i<=sqrt(x);i++){
if(x%i==0)return 0;
}
return 1;
}
void dfs(int k){//k是第 k个数字
for(int i=1;i<=20;i++){
if(k==1||(i+a[k-1])%2==1){//除2以外,质数都是奇数
if(f[i]==0&&(k==1||zs(i+a[k-1]))){//判断数是否已被占用,如果是第一个数不需要判断和为素数
a[k]=i;f[i]=1;//标记数被占用
if(k==20&&zs(a[k]+a[1])){
print();//20个数已满且首尾相加为素数输出
exit(0);
}
else dfs(k+1);
f[i]=0;
}
}
}
}
int main(){
dfs(1);
return 0;
}