八皇后问题详解
著名的八皇后问题是由棋手马克斯·贝瑟尔在1848年提出来的,要求在 8 × 8 的棋盘上摆放8个皇后,使”皇后“们不能互相攻击 ,当任意两个皇后都不处于同一行、同一列或同一条斜线上时就不会相互攻击,即为目标解。
例如下图:
读完上面的内容,想必您已经对此问题有了一定的认识,也就是我们需要在一个8 × 8的矩阵中摆放8个不在同一行,不在同一列,并且不在同一对角线上的棋子,计算出有多少种摆放的方法。
我们知道在一个矩阵中的同一个右对角线上所有元素的横坐标和纵坐标之和是一个定值,即横坐标与纵坐标之和,而同一左对角线上的所有元素的坐标也有特点,即都是纵坐标与横坐标的差值。可以看下图:
那么这个时候,用深度优先搜索就能够轻易的解决问题了,以下是我的代码,代码里包含详细注释,可以根据注释来理解。
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
//标记数组
bool vis[30]={false};//列的标记数组,初始为false
bool lr[30]={false};//左对角线的标记数组,初始为false
bool fr[30]={false};//右对角线的标记数组,初始为false
int cnt=0;//记录所有摆放方法的数量
const int n = 8;
bool judge(int x,int y)//判断当前位置是否能摆放皇后,当前位置为(x,y)
{
if(vis[y] || lr[y-x+n] || fr[x+y])
return false;
return true;
}
void dfs(int x)
{
if(x==n)//结束条件:摆放的个数达到n个,在这里即8个
{
cnt++;
return ;
}
for(int i=1;i<=n;i++)//遍历所有情况,i表示列,即纵坐标
{
if(!judge(x,i))//判断条件,如果不能摆放就continue
continue;
//标记已走过
vis[i]=true;
lr[i-x+n]=true;
fr[x+i]=true;
dfs(x+1);//在i行已经有棋子后开始下一行
//撤回标记,不影响下一次的落棋
vis[i]=false;
lr[i-x+n]=false;
fr[x+i]=false;
}
return ;
}
int main()
{
dfs(0);
cout<<cnt<<endl;
return 0;
}
这个八皇后是最基础的部分,算是如个门,知道是个咋回事,如果这题懂了之后,推荐可以做一下相关的扩展题目,比如N*M的棋盘下n个棋子等等,希望此篇题解对您有所帮助,再见。