回溯的意义是找到所有可能的解,而不是一个解
其实一经过分析,也没有想象中的那么难。
1.这道题我们是要考虑放置皇后的位置,我们要兼顾到横坐标、也要兼顾到纵坐标。可我们根据观察横坐标、纵坐标都有一个从1到n递增的顺序。我们可以把横坐标按照从1到n的顺序,这样不会重复,而我们只需要管纵坐标即可,这样会大大减小难度。
2.如果说我们横坐标1到n找,那么肯定不会重复。我们看纵坐标、相对应主对角线、副对角线是否重复。根据观察我们可以得到其记录的规律。
3.我们通过算是递归的形式来完成的吧,我们需要一个递归出口,来结束调用递归,k>n结束,执行打印。
4.最后一个是关于为什么要回溯,这有点涉及到对递归的理解了。举一个例子吧,可能不是那么严谨,假如说n=7,我们递归到第6层的位置,假如说纵坐标为3符合条件,那么我们将位置进行true的标记,递归进入下一层。我们进入第7层的位置,那么纵坐标我们就得从1到7找是吧,假如说2的位置符合条件,那么我们进行下一次递归(也就是打印),然后我们需要把标记给移除,纵坐标继续循环3…n的位置是否符合题意。第7层结束后,我们还要返回到第6层,开始找第6层纵坐标第4…n是否有符合条件的,在进行递归,第7层向之前一样,又来了一遍。假如说我们不回溯,我们我们只有一种解,二我们的目的是所有解。
语言描述或许还是不太明白,可以看一下B站一位up主的视频,讲解的视频非常详细。
#include<bits/stdc++.h>
using namespace std;
const int maxn=30;
int n,cnt;
int p[maxn];
bool tx[maxn],ty[maxn],x[maxn];
void print(){
cnt++;
if(cnt<=3){
for(int i=1;i<=n;i++){
printf("%d ",p[i]);
}
cout<<endl;
}
}
void dfs(int k){
if(k>n){
print();
}
for(int i=1;i<=n;i++){
if(tx[k-i+n]||x[i]||ty[i+k])continue;
tx[k-i+n]=true;
x[i]=true;
ty[i+k]=true;
p[k]=i;
dfs(k+1);
tx[k-i+n]=false;
x[i]=false;
ty[i+k]=false;
}
}
int main(){
scanf("%d",&n);
dfs(1);
printf("%d\n",cnt);
}