八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。
该问题是国际西洋棋棋手马克斯·贝瑟尔于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;
}