八皇后问题:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
八皇后问题本质上是排列问题。
具体分析[来自<剑指Offer>]:
“由于8个皇后的任意两个不能处在同一行,那么肯定是每一个皇后占据一行。于是定义一个数组ColumnIndex[8],数组中第i个数字表示位于第i行的皇后的列号。先把数组ColumnIndex的8个数字分别用0~7初始化,接下来就是对数组ColumnIndex做全排列。然后只需要分析每个排列对应的8个皇后是不是在同一对角线上,即是不是有i-j == ColumnIndex[i] - ColumnIndex[j]或j-i == ColumnIndex[i] - ColumnIndex[j]成立。”
而C++标准库算法bool next_permutation( BidirIt first, BidirIt last) 正好提供了对[first, last)元素的排序。该函数实现就地排列,如果还有下个排列,则将原序列改为下个排列,并返回true,表示排列成功。
利用标准库的算法,省去了许多的代码。
#include
#include
#include
/* 使用next_permutation */
using namespace std;
int ColumnIndex[]={0,1,2,3,4,5,6,7};
/* 判断是否不是位于同一对角线上 */
bool isNotInDigonal( int *columnindex ) {
for( int i = 0; i < 8; ++i ) {
for( int j = i + 1; j < 8; ++j ) {
if( i - j == columnindex[i] - columnindex[j]
|| j - i == columnindex[i] - columnindex[j] )
return false;
}
}
return true;
}
int main()
{
ofstream outFile("EightQueensSolutions.txt"); /* 保存每个解 */
size_t cnt = 0;
/* while循环每次得到下一个排列 */
while( next_permutation( begin(ColumnIndex), end(ColumnIndex))) {
if( isNotInDigonal( ColumnIndex ) {
++cnt;
for( auto const &i : ColumnIndex )
outFile << i << " ";
outFile << endl;
}
}
outFile.close();
cout << "total count: " << cnt << endl; /* 解的总数: 92 */
return 0;
}