问题描述:在n×n格的棋盘上放置彼此不受攻击的n个皇后。即任意两个皇后不得处在同一行、同一列或者同一对角斜线上。下图中的每个黑色格子表示一个皇后,这就是一种符合条件的摆放方法。请求出总共有多少种摆法。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
思路:每个皇后都是放在单独的一行,因此同行就不用判断了。用一个数组记录每个皇后可能的列位置,比如Col[0]表示皇后0所在的列号,0到 n-1 之间的值。对于每一种排列,检查是否有在同一列或者同一对角线的两个皇后。产生全排列的算法可以参考字符串的排列。
这种方法很简单,但是效率太低了。可以改进一下,采用回溯的思想。首先考虑皇后0所在的列号,取0到7的一个。然后考虑皇后1,检查每一个可能的列号,如果与皇后0没有冲突,那么考虑皇后2;如果与皇后0有冲突,那么直接返回,继续考虑已经没有意义。
参考代码:NQueenProblem(8)计算8后问题
//函数功能 : 检查皇后cur的摆法
//函数参数 : n为皇后数,cur为当前检查的皇后,col为皇后的列位置,sum为找到的摆法
//返回值 : 无
void Queen(int n, int cur, int *col, int *sum)
{
if(cur == n) //找到一种摆法
{
for(int i = 0; i < n; i++)
cout<<col[i]<<' ';
cout<<endl;
(*sum)++; //摆法加1
return;
}
int i, j;
for(i = 0; i < n; i++) //考虑每一个可能的列号
{
//检查当前考虑的皇后是不是可以放在位置i
for(j = 0; j < cur; j++)
{
if(abs(j-cur) == abs(col[j]-i) || col[j] == i) //与之前的皇后有冲突,不用考虑下一个皇后了
break;
}
if(j == cur)
{
col[cur] = i; //可以放在这个位置
Queen(n, cur+1, col, sum); //考虑下一个皇后
}
}
}
//函数功能 : n皇后的摆法
//函数参数 : n为皇后数
//返回值 : 摆法的数量
int NQueenProblem(int n)
{
int *col = new int[n];
int sum = 0;
Queen(n, 0, col, &sum); //调用核心函数
delete [] col;
col = NULL;
return sum;
}
本人享有博客文章的版权,转载请标明出处 http://blog.youkuaiyun.com/wuzhekai1985