八皇后问题
八皇后问题是一个经典的题目,在棋盘上放置8个皇后,使得他们不互相攻击,此时每个皇后的的攻击范围为同列同行和同对角线,要求找出所有的解。
本题的算法来自于《算法竞赛入门经典》
在分析问题的时候可以发现,在放置八个皇后的时候,恰好是每行每列都要放置一个皇后,那么我们放置皇后的时候就可以忽略行或者列,在放置皇后的时候只需要考虑逐行放置皇后,然后再考虑皇后的冲突问题。例如用C[X]表示第X列的列编号,就可以大大提高效率。
#include<iostream>
using namespace std;
#define N 20
int tot=0;//解的数目
int C[N];
int n=8;
void search(int cur){
//cur为当前放置皇后的行数
if(n==cur){
tot++;
cout<<"第"<<tot+1<<"种解法"<<endl;
for(int i=0;i<n;i++){
cout<<i<<" "<<C[i]<<endl;
}
}
else for(int i=0;i<n;i++)
{
int ok=1;
C[cur]=i;
for(int j=0;j<cur;j++)
if(C[cur]==C[j]||cur-C[cur]==j-C[j]||cur+C[cur]==j+C[j])//检查对角线和y方向是否冲突
{
ok=0;
break;
}
if(ok)
search(cur+1);
}
}
int main(){
search(0);
cout<<tot;
return 0;
}
其中最重要的就是在于判断皇后是否冲突,因为在放置的时候的逐行放置的所以在判断的时候只需要考虑纵向和主对角线和副对角线的攻击即可。
C[cur]==C[j]||cur-C[cur]==j-C[j]||cur+C[cur]==j+C[j]
这样便可以解决八皇后问题了。
在该算法的基础上,还可以继续改进,可以使用一个二维数组去直接保存已经存在放置皇后的位置。进一步改进程序
void search(int cur){
if(n==cur)
tot++;
else for(int i=0;i<n;i++)
{
if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]){//利用二维数组直接判断是否冲突
C[cur]=i;
vis[0][i]=vis[1][cur+i]=[cur-i+n]=1;
search(cur+1);
vis[0][i]=vis[1][cur+i]=[cur-i+n]=0;
}
}
}