首先,搜索就是找到你想找到的所有情况。那深搜就是如野牛冲锋般一直冲向最深处,等到冲不动了(树的分支到底了),就需要回溯。原理如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/8c673fca29d3c6cbd987975a42a3a6e7.png)
在使用深搜时,系统会生成一个栈,栈的出入顺序如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/ab8c282cfcc69b79a98c90a566c15dc5.png)
于是我们就可以写出基础代码(全排列问题)
![](https://i-blog.csdnimg.cn/blog_migrate/79d3ba7d9dd65e16a4f3985a18f24523.png)
代码:
#include<bits/stdc++.h>
using namespace std;
int a[15];//存排列答案
int v[15];//查看是否被使用
int n;
void dfs_quan_pai_lie(int i){
if(i==n+1){//边界条件
for(int k=1;k<n+1;k++){
cout<<a[k];
}
cout<<endl;
return;
}
for(int j=1;j<=n;j++){
if(v[j]==0){//假如备用了就不能再用
a[i]=j;
v[j]=1;
dfs_quan_pai_lie(i+1);//回溯
v[j]=0;
}
}
}
int main(){
cin>>n;
dfs_quan_pai_lie(1);
return 0;
}
我们得到了全排列问题的代码那我们就能稍加修改,写出素数环问题:
![](https://i-blog.csdnimg.cn/blog_migrate/56ef7eb04ffefc0b826434ac6b0ba549.png)
我们可以将素数环切开展成一个数组:
![](https://i-blog.csdnimg.cn/blog_migrate/a30626d12c4668567a45fb27ca300a85.png)
要知道如何使相邻两个数的和是素数?------
bool isprime(int x){
if(x==1){
return false;
} //特判
for (int i=2; i<=sqrt(x); i++) {
if(x%i==0){ //利用素数性质判断
return false;
}
}
return true;
}
于是我们就可以得出代码:
void dfs(int i){
if(i==n+1){//边界条件
for(int k=1;k<n+1;k++){
cout<<a[k]<<" ";
}
return;
}
for(int j=1;j<=n;j++){
if(v[j]==0){//判定
if(isprime(a[i-1]+j)){
a[i]=j;//第i部放j
v[j]=1;
dfs(i+1);//回溯
v[j]=0;
}
}
}
}
但是这个代码只是一个一维数组形式,我们需要使用数组第一项与数组最后一项进行判断,上代码!
#include<bits/stdc++.h>
using namespace std;
int a[15];//存排列答案
int v[15];//查看是否被使用
int n;
bool isprime(int x){
if(x==1){
return false;
}
for (int i=2; i<=sqrt(x); i++) {
if(x%i==0){
return false;
}
}
return true;
}
void dfs(int i){
if(i==n+1){//边界条件
if(isprime(a[1]+a[n])) {
for(int k=1;k<n+1;k++){
cout<<a[k]<<" ";
}
cout<<endl;
}
return;
}
for(int j=1;j<=n;j++){
if(v[j]==0){//判定
if(isprime(a[i-1]+j)){
a[i]=j;//第i部放j
v[j]=1;
dfs(i+1);//回溯
v[j]=0;
}
}
}
}
int main(){
cin>>n;
a[1]=1;
v[1]=1;
dfs(2);
return 0;
}
绝杀,无解!