一:引入:
八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。如图所示:
二:分析:
纵边和横边容易解决,主要是两条斜边比较难来判断,仔细观察一下紫线,发现其在这8*8的方格的走向有点像一元方程的图像,我们是不是可以用y=bx+c这个方程来代替斜线呢?
首先,两条线是垂直的,因此一条线的解析式为y=x+c那么截距c为y-x为了避免负数的出现,我们需要加上方格的边即8,因此c=y-c+8,同理,另一条边的解析式为c=y+x,这是没有负数的可以直接使用。最后我们所以的准备工作就完成了。
三:代码实现:
下面是洛谷的八皇后问题的代码实现,(虽然可以用打表作弊过。。。。。。)
#include<bits/stdc++.h>
using namespace std;
const int N = 15;
int a[N];
bool lie[N],ab[2*N],ba[2*N];//斜线一定要开两倍,开N会爆 导致在8之后的皇后会出错
//不用行的原因是因为我用的一维数组实现的。
int n,ans;
void dfs(int x)
{
if(x>n)//如果放完了意味着可以输出一次
{
if(ans<3)//限制只输前三个
{
for(int i=1;i<=n;i++)cout<<a[i]<<' ';
cout<<endl;
}
ans++;
return ;
}
for(int i=1;i<=n;i++)
if(!lie[i]&&!ab[x+i]&&!ba[n-i+x])
{
a[x]=i;
lie[i]=ab[x+i]=ba[n-i+x]=true;
dfs(x+1);
lie[i]=ab[x+i]=ba[n-i+x]=false;//恢复现场
}
}
int main()
{
cin>>n;
dfs(1);//从第一个皇后开始放
cout<<ans;
return 0;
}
三:总结:
八皇后问题主要是运用dfs算法去解决,而dfs关键的一定就是要知道哪个位置要记录被搜过,而且要看需不需要恢复现场,有的在树的深搜下是不需要恢复现场的,总而言之,言而总之,要比较熟练地掌握dfs。