八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。由此推进到n皇后的问题。
思路分析:
1 利用暴力的方式,根据规则不难推出,每行有且仅有一个皇后。所以,我们采用一个queen[]一维数组来表示第几行的皇后位于第几列。
2 采用递归的实施方式,对整个棋盘进行搜索,直到找到所有解为止
难点:如何判断这个位置是否可用?
根据思路分析得到的情况,我们可以将整个棋盘作为一个坐标系,然后因为每层确定位置以后,需要判断跟前面的皇后有没有冲突,所以本身这一行不需要判断。我们只需要判断前几行的皇后所在的列和斜线(采用横坐标相减绝对值与纵坐标相减的绝对值(因为斜线的斜率刚好为1))是否和本行的皇后冲突。即queen[t]==queen[i]和abs(queen[t]-queen[i])==abs(t-i)
问题解决!!
具体代码如下:(vc6.0 c++)
#include<iostream>
#include<cstdio>
#include<cmath>
usingnamespace std;
#define N 15
intsum=0;
intn;
intqueen[N];
boolplace(int t)//放置判断函数(判断将该皇后放置的这个位置与前方的其他皇后有无冲突)
{
for(int i=1;i<t;i++)
if(abs(i-t)==abs(queen[i]-queen[t])||queen[i]==queen[t])//核心(利用坐标判断)
return false;
return true;
}
intsearch(int t)//查找函数(每一层)从第一层开始,也是递归的本体
{
if(t>n&&n>0) sum++;//放置了n行
for(int i=1;i<=n;i++)
{
queen[t]=i;//将第t行的皇后位置确定为i
if(place(t))//如果当这时与前方的皇后无冲突
search(t+1);//查找下一个
}
return sum;
}
intmain()
{
while(~scanf("%d",&n))//多次测试
{
sum=0;//每次将累计函数归零
printf("%d\n",search(1));
}
return 0;
}