递归思路:把棋盘存储为一个1维数组数组大小为N+1,即a[N+1],数组中第i个元素的值代表第i列的皇后位置,这样便可以把问题的空间规模压缩为一维O(N),在判断是否冲突时也很简单,首先每列只有一个皇后,且在数组中只占据一个元素的位置,列冲突就不存在了,其次是行冲突,判断是否有a[i]与当前要放置皇后的行k相等即可。至于斜线冲突,通过观察可以发现所有在斜线上冲突的皇后的位置都有规律即它们所在的行列互减的绝对值相等。这样某个位置是否可以放置皇后的问题已经解决。
非递归思路:同样把棋盘存储为一个1维数组a[N+1],数组中第i个元素的值代表第i行的皇后位置,首先对N行中的每一行进行探测,寻找该行中可以放置皇后的位置,对该行的每一列进行探测,看是否可以放置皇后,如果可以,则在该列放置一个皇后,然后继续探测下一行的皇后位置。如果已经探测完所有的列都没有找到可以放置皇后的列,此时就应该回溯,把上一行皇后的位置往后移一列,如果上一行皇后移动后也找不到位置,则继续回溯直至某一行找到皇后的位置或回溯到第一行,如果第一行皇后也无法找到可以放置皇后的位置,则说明已经找到所有的解程序终止。如果该行已经是最后一行,则探测完该行后,如果找到放置皇后的位置,则说明找到一个结果,打印出来。但是此时并不能再此处结束程序,因为我们要找的是所有N皇后问题所有的解,此时应该清除该行的皇后,从当前放置皇后列数的下一列继续探测。
递归思路代码:
#include<iostream>
#include<stdio.h>
using namespace std;
int num = 0;bool Place(int *ar,int k)
{
for(int j = 1;j<k;++j)
{
if(ar[k] == ar[j] || abs(k-j) == abs(ar[k] - ar[j]))
{
return false;
}
}
return true;
}
void PrintAr(int *ar,int n)
{
for(int i = 1;i<=n;++i)
{
for(int j= 1;j<=n;++j)
{
if(ar[j] == i)
{
cout<<'Q';
}
else
{
cout<<"# ";
}
}
cout<<endl;
}
cout<<endl;
}
void nQueue(int *ar,int k,int n)
{
if(k > n)
{
num+=1;
PrintAr(ar,n);
}
else
{
for(int i = 1;i<=n;++i)
{
ar[k] = i;
if(Place(ar,k))
{
nQueue(ar,k+1,n);
}
}
}
}int main()
{
const int n = 8;
int ar[n+1]={0};
nQueue(ar,1,n);
cout<<num<<endl;
return 0;
}
非递归思路代码:
int main()
{
const int n = 8;
int ar[n+1]={0};
int k = 1;
ar[k] = 0;
while(k >= 1)
{
ar[k]+=1;
while(ar[k] <= n && !Place(ar,k))
ar[k]+=1;
if(ar[k] <= n)
{
if(k >= n)
{
PrintAr(ar,n);
num ++;
}
else
{
k+=1;
ar[k] = 0;
}
}
else
{
--k;
}
}
cout << num << endl;
return 0;
}