1213:八皇后问题
时间限制: 1000 ms 内存限制: 65536 KB
【题目描述】
在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。
【输入】
(无)
【输出】
按给定顺序和格式输出所有八皇后问题的解(见样例)。
题目要求:不能是同一列、同一行、同一斜线(两个方向的对角线
思路:
abs(a[i]-a[l])==abs(i-l)
#include<bits/stdc++.h>
using namespace std;
int n=8,num=1;
int a[9]={0};
void dfs(int l);
int check(int l);//判断同一列/同一行/一条斜线上是否已经有皇后,传入参数为第几行
void print();
int main(){
dfs(1);
return 0;
}
void print(){
// 按行输出
// for(int i=1;i<=n;i++){
// for(int j=1;j<=n;j++){
// if(j==a[i]) cout<<1<<" ";
// else cout<<0<<" ";
// }
// cout<<endl;
// }
//按列输出 ,按列实质就是矩阵倒置,由于是一维数组储存 所以只需要将第n行m行转化为第m列的n行即可
int b[9];
for(int i=1;i<=n;i++){
b[a[i]]=i;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(j==b[i]) cout<<1<<" ";
else cout<<0<<" ";
}
cout<<endl;
}
}
void dfs(int l){
//先判断是否需要结束该次遍历
if(l==n+1){
cout<<"NO. "<<num<<endl;
print();
num++;
return ;
}else{
//先循环遍历,i表示第几列
for(int i=1;i<=n;i++){
a[l]=i;//直接先赋值,否则会出错 (他会往下继续判断,然后再搜索下一行,如果该位置判断有问题,会回退到上一行,)
if(check(l)){ //判断
dfs(l+1);
}
}
return;
}
}
int check(int l){
for(int i=1;i<l;i++){ //即在l-1行才确定皇后的位置,后面的就不需要遍历判断了
if((a[i]==a[l])||(abs(a[i]-a[l])==abs(i-l))) { //a[l]表示的当前行所在列数
return 0;
}
}
return 1;
}
问题实质为:搜索、回溯
该搜索问题的实质是深度优先的算法(且为左根右):为了求得问题的解,先选择某一种可能情况开始搜索,在搜索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向下搜索,如此反复进行,直至得到解或证明无解。
最终搜索的结果得到一个二叉树。而向下搜索的和回溯都可以利用递归去实现。
回溯是回到上一步然后再向下搜索,所以是基于第一次选择的条件下搜索,直到所有情况搜索完才会换到另外的选择继续搜索
以下是二叉树搜索的过程,根节点表示满足条件的 结果(4次搜索完成)