一、什么是N皇后问题?
在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上。
二、算法
1、将第一个皇后放置在第一行的第一个空格里
2、对于第二行,从第一个空格开始寻找不与第一行的皇后冲突的空格。找到的第一个不冲突的空格是第2个。
3、对于第三行,这时已经找不到与之前放置的两个皇后不冲突的空格了。把当前行恢复初始状态,返回到上一行。
4、在当前行皇后所占的空格之后寻找一个不与之前皇后冲突的位置。有两种情况,如果找打了则把当前行的皇后移动到该位置,然后处理下一行。如果直到最后当前行的最后一个空格也没有找合适的位置,则把当前行恢复初始状态,继续回溯到上一行。
5、把最后一个皇后成功安置在最后一行,代表找到了一种可行解。返回步骤4。
6、当需要回溯到第0行(表格之外)的时候代表已经找遍了所有可能的可行解。
三、4皇后解法图解
第一步
Q |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
第二步
Q |
|
|
|
|
| Q |
|
|
|
|
|
|
|
|
|
第三步 发现第三行没有合适的位置了,于是将第二行皇后的位置移到下一个不冲突的位置
Q |
|
|
|
|
|
| Q |
|
|
|
|
|
|
|
|
第四步
Q |
|
|
|
|
|
| Q |
| Q |
|
|
|
|
|
|
第五步 发现第四行没有合适的位置了,于是回溯到第二行,又发现第二行到头了,于是继续回溯到第一行。把第一行皇后的位置后移。
| Q |
|
|
|
|
| Q |
|
|
|
|
|
|
|
|
第六步
| Q |
|
|
|
|
| Q |
Q |
|
|
|
|
|
|
|
第七步
| Q |
|
|
|
|
| Q |
Q |
|
|
|
|
| Q |
|
四、程序
#include "stdafx.h"
#include <iostream>
using namespace std;
int n=0;
int arr[100];
bool place(int i) //判断能不能放置第N个皇后
{
for(int j=0;j<i;j++)
if(arr[j]==arr[i]||abs(arr[j]-arr[i])==abs(j-i))
return false;
return true;
}
int queue(int n)
{
int solution=0;
for(int i=0;i<n;i++)
arr[i]=0;
int k=1;
while(k>=0)
{
while(!place(k)&&k<n) //放置第N个皇后
arr[k]=arr[k]+1;
if(arr[k]<n&&k==n-1) //排列完成一次
{
solution++;
arr[k]=arr[k]+1;
}
else if(arr[k]<n&&k<n-1) //排列完一个皇后
{
k=k+1;
arr[k]=-1;
}
else //当前皇后没有合适的位置
{
arr[k]=0;
k=k-1;
arr[k]=arr[k]+1;
}
}
return solution;
}
void main()
{
while(1)
{
cout<<"Please input the queue number:"<<endl;
cin>>n;
if(n==-1)
break;
int x=queue(n);
cout<<x<<" solution(s)"<<endl;
}
system("pause");
}
五、N皇后问题解的个数
n solution(n)
1 1
2 0
3 0
4 2
5 10
6 4
7 40
8 92
9 352
10 724
11 2680
12 14200
13 73712
14 365596
15 2279184
16 14772512
17 95815104
18 666090624
19 4968057848
20 39029188884
21 314666222712
22 2691008701644
23 24233937684440
24 227514171973736
25 2207893435808352
以上结果可以作为测试案例验证程序。