问题:在 n×n 的国际象棋上摆放n个皇后,使其不能相互攻击,即任意两个皇后不得处 在同一行、同一列或者同一对角斜线上。下图中的每个黑色格子表示一个皇后,这就是一种 符合条件的摆放方法。请求出总共有多少种不同的摆法。
(1)定义判断函数:不同行(每行只放置一个皇后);不同列(放置前进行遍历,即将放置的皇后与之前所有皇后所在列不同);不同斜线(放置前进行遍历,即将放置的皇后与之前所有皇后练成线的斜率不为±1)
(2)定义递归的回溯函数,并调用判断函数。若在该行遍历完n之前能够找到位置放置皇后,则向下一行递归,若没有位置,则向上回溯。如果棋盘所有行列寻找完毕,则解的个数+1
·输入:N
·摆皇后:
1输出:
(最后一步进行)利用循环进行所有皇后位置的输出,因为皇后位置从0开始,所以输出形式要加1
2进行第k个皇后位置的逐个判断:
k为判断的本行,i为判断的本列
j为判断的上面已经摆好的是否与当前冲突,j从0-k-1行全部判断一遍
非同列——位置不等于上一级的位置(循环次数)
非对角线上——列差!=行差 (|queenPos[j]-i|!=|k-j|)
如果判断成功,则进行下一轮判断,如果不成功则break返回上一级
3如果判断完毕,则进行下一列的判断
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int N;
int queenPos[100];//用来存放算好的皇后位置,最左上角是(0,0)
void NQueen(int k);
int main()
{
cin>>N;
NQueen(0);//从第0行开始摆皇后
return 0;
}
void NQueen(int k)//在0~k-1行皇后已经摆好的情况下 ,摆第k行及其以后的皇后
{
int i;
if(k==N)//N个皇后已经摆好
{
for(i=0;i<N;i++)
cout<<queenPos[i]+1<<" ";
cout<<endl;
return ;
}
for(i=0;i<N;i++)//逐个尝试第k个皇后的位置
{
int j;
for(j=0;j<k;j++)
{
if(queenPos[j]==i||abs(queenPos[j]-i)==abs(k-j))
{
break;//冲突,测试下一个位置
}
}
if(j==k)
{
queenPos[k]=i;
NQueen(k+1);
}
}
}