书中 P200 给出了不同于以往利用回溯法解决八皇后问题的思路,但是没有给出代码,下面对这种算法进行实现。
首先给出书中的解释:
由于 8 个皇后的任意两个均不能处于同一行,所以每一个皇后占据一行。于是可以定义一个数组 ColumnIndex[8],数组中第 i 个数字表示位于第 i 行的皇后的列号。首先将数组 ColumnIndex 的 8 个数字分别用 0~7 进行初始化,然后对数组 ColumnIndex 进行全排列。因为我们使用不同的数字初始化数组,所以任意两个皇后肯定不同行且不同列。因此,只需要确定每一个排列对应的 8 个皇后是不是在同一条对角线上,也就是对于数组的两个下标 i 和 j,是否满足
i-j == ColumnIndex[i]-[j] || j-i == ColumnIndex[i]-ColumnIndex[j]
即可。
实现具体代码如下所示:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
void EightQueen(vector<int> ColumnIndex, vector<vector<int>>& result, int start);
int main()
{
int N;
cin>>N;
vector<int> ColumnIndex; // 表示位于第 i 行的皇后的列号
ColumnIndex.reserve(static_cast<unsigned long>(N));
for(int i =0;i< N;i++)
ColumnIndex.push_back(i);
vector<vector<int>> res;
EightQueen(ColumnIndex,res, 0);
cout<<res.size()<<endl;
cout<<endl;
return 0;
}
void EightQueen(vector<int> ColumnIndex, vector<vector<int>>& result, int start)
{
if(start == ColumnIndex.size()-1)
{
bool res = true;
// 检查这种排列是不是符合要求
for(int i = 0;i<ColumnIndex.size();i++)
{
for(int j =0;j<ColumnIndex.size();j++)
{
if (abs(i - j) == ColumnIndex[i] - ColumnIndex[j] && i!=j)
{
res = false;
break;
}
}
if(!res)
break;
}
if(res)
result.push_back(ColumnIndex);
}
else
{
for(int i = start;i<=ColumnIndex.size()-1;i++)
{
swap(ColumnIndex[i],ColumnIndex[start]);
EightQueen(ColumnIndex, result, start+1);
swap(ColumnIndex[i],ColumnIndex[start]);
}
}
}