C++刷题 搜索与回溯法解素数环(搜索与回溯算法)
文章标签:
c++刷题软件
【问题描述】将1~n这n个数字首尾相连,形成一个圆环,要求圆环上任意两个相邻的数字之和都是一个素数,请编程输出符合条件的素数环。
输入
输入数据仅一行,包含一个正整数n(n<=20)。
输出
输出数据最多包括20行,每行由n个整数组成,表示前十个符合条件的素数环(不足20个时全部输出)。所有素数环第一个元素必须是1,且按照从小到大的顺序排列。
样例输入 样例输出
【算法分析】
很明显,这是一道回溯的题目。从1开始,每个空位有n种可能,只要填进去的数满足以下条件:与前面的数不相同并且与左边相邻的数的和是一个素数。第n个数还要判断和第1个数(本题要求第1个数为1)的和是否素数
【算法流程】
1、数据初始化; 2、递归填数:判断第i个数填入是否合法;
A、符合要求:填数;判断是否到达目标(n个已填完):是,打印结果;不是,递归填下一个;
B、不符合要求:选择下一种可能;
【参考程序】
#include<bits/stdc++.h>
using namespace std;
int search(int k) ;
bool b[21]={0};
int a[21]={0};
int n,num=0;
int main()
{
int i,j;
cout<<"请输入:";
cin>>n;
a[1]=1;//首位固定为1
if(n%2==0) //只有偶数个数才可能构成素数环
search(2);
return 0;
}
bool isprime(int x,int y) //判素数
{
if(x+y<2)
return 0;
for(int i=2;i<=sqrt(x+y);i++)
{
if((x+y)%i==0)
return 0;
}
return 1;
}
int search(int k) // 回溯
{
if(num>=20||k>n)//如果超过20种方案退出
return 0;
for(int i=2;i<=n;i++)//从2到n可以选择
{
if(!b[i]&&isprime(a[k-1],i))// 判断相邻数为是否素数、该数是否可用并从小到大排序
{
a[k]=i;
b[i]=1;
if(k==n)
{
if(isprime(a[n],a[1]))
{
num++;
for(int j=1;j<=n;j++)
cout<<a[j]<<' ';
cout<<endl;
}
}
else
search(k+1);
b[i]=0;
}
}
}