皇后问题:
由n*n个方块排成n行n列的正方形称为“n元棋盘”。如果两个皇后位于棋盘上的同一行或同一列或同一对角线上,则称她们为互相攻击,现要求找使N元棋盘上的n个皇后互不攻击的所有布局。
假设棋盘上每一行放置一个皇后,分别用自然数0,1,2,.......,n-1。
首先定义一个长度为n的一维数组q,其中每一个元素去q[i](i=0,1,2,.......,n-1),随时记录第i行皇后所在的列数。
初始时,先将各皇后放在各行的第0列。即数组q的初值为:q[i]=0, i=0,1,2,.......,n-1
另外第i行与第j行上的皇后在某一对角线上的条件为去|q[i]-q[j]|=|i-j|;而它们在同一列的条件为q[i]=q[j];
回溯法算法步骤如下:
对于第i行的皇后,假设前i-1个皇后互相不攻击,现在来安排第i个皇后使它与前面n-1个皇后互相不攻击就可以了。
【1】q[i]=n时,表示最后一列也搜索结束,无法安排第i行的皇后,令q[i]=0,回退一行,考虑重新安排第i-1行的皇后,使第i-1行的皇后向右搜索q[i-1]=q[i-1]+1;找到使第i-1行与前i-2行互不攻击的下一个位置,如果退回到第-1行(实际没有这一行),表示搜索结束,退出。
【2】当q[i]<n,由于初始q[i]=0;从第0列开始向右搜索,,需要检查第i行上的皇后与前面的从第0行到第i-1均不互相攻击,才算成立,可以考虑下一行的皇后即i=i+1;若不成立,q[i]=q[i]+1,重复前面的步骤。
【3】若安排好了第n-1行的皇后,说明搜索到了一个n皇后互不攻击的布局,可将其保存输出。然后将第n-1行皇后向后移动,即q[n-1]=q[n-1]+1,重复上述步骤,搜索一个皇后布局。
具体实现代码
#include "iostream"
#include <cmath>
using namespace std;
bool place(int k,int*q)//考察皇后k放置在x[k]列是否发生冲突
{
int i;
for(i=0;i<k;i++)
if(q[k]==q[i]||abs(k-i)==abs(q[k]-q[i]))
return false;
return true;
}
void n_queen(int n,int*q)
{
int k=0;
while(k>=0)
{
while(q[k]<n&&!place(k,q))
q[k]++;
if(q[k]==n)
{q[k--]=0;q[k]++;}
else
if (k==n-1)
{
for(int i=0;i<n;i++)
cout<<q[i]<<' ';
cout<<endl;
q[k]++;
}
else
{
k++;
}
}
}
void main(void)
{
int n;
cin>>n;
int* q=new int[n];
for(int i=0;i<n;i++)
q[i]=0;
n_queen(n,q);
}