八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。
该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,
即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
计算机发明后,有多种计算机语言可以解决此问题。
如下用c++代码实现:
算法说明:
结构:用一个一维数组表示8皇后排放的位置。(如下图)
算法说明:
现尝试再第一列的任意位数放皇后,然后在尝试在第二列的任意位置放皇后,依次迭代。
迭代到第8行,如果有成功的就将摆法数加1。
一维数组的复制组合全部实验过后,程序结束。
回溯点:
1.
gCount++, print();
gEightQueen[index] = 0;
2.
eight_queen(index + 1);
gEightQueen[index] = 0;
上面的说明希望有利于您的理解,哦,在加一句总结。
回溯法的关键就是设计一个可回溯的数据结构,这是关键,就像该问题的一维数组(gEightQueen[8] )一样。
#include<iostream>
using namespace std;
static int gEightQueen[8] = { 0 }, gCount = 0;
void print()//输出每一种情况下棋盘中皇后的摆放情况
{
for (int i = 0; i < 8; i++)
{
int inner;
for (inner = 0; inner < gEightQueen[i]; inner++)
cout << "0";
cout <<"#";
for (inner = gEightQueen[i] + 1; inner < 8; inner++)
cout << "0";
cout << endl;
}
cout << "==========================\n";
}
int check_pos_valid(int loop, int value)//检查是否存在有多个皇后在同一行/列/对角线的情况
{
int index;
int data;
for (index = 0; index < loop; index++)
{
data = gEightQueen[index];
if (value == data)
return 0;
if ((index + data) == (loop + value))
return 0;
if ((index - data) == (loop - value))
return 0;
}
return 1;
}
void eight_queen(int index)
{
int loop;
for (loop = 0; loop < 8; loop++)
{
if (check_pos_valid(index, loop))
{
gEightQueen[index] = loop;
if (7 == index)
{
gCount++, print();
gEightQueen[index] = 0;
return;
}
eight_queen(index + 1);
gEightQueen[index] = 0;
}
}
}
int main(int argc, char*argv[])
{
eight_queen(0);
cout << "total=" << gCount << endl;
return 0;
}