八皇后问题是一个古老而著名的问题。该问题要求在8x8格的国际象棋盘上摆放着8个皇后,使其不能互相攻击(如下图所示)。即任意两个皇后都不处于同一行、同一列或同一斜线上。求总共有多少种摆法。如图所示:
递归算法很容易写出,现在的问题是如何利用堆栈实现八皇后问题的求解。
思路:建立一个数值栈用于存储已摆放好的棋子所在的行号以及当前的摆放进度。
typedef struct SqStack {
int row[MAX_SIZE + 1]; //为了方便起见数组下标从1开始 记录棋子的行号
int top; //栈顶指针
}SqStack;
如果我要求第k列棋子的摆放位置,只需要试探第k列中的每一个行号,然后用一个变量i遍历第1~k-1列,如果其中某列的棋子的行号与试探的行号相等或者位置在同一个斜线上,则该位置不满足,继续寻找。
for (int i = 1; i <= col - 1; i++) {
if (s.row[i] == row || (col - i) == abs(row - s.row[i]))
return 0;
}
如果成功找到了一个位置,执行入栈操作,寻找下一列棋子的摆放位置。如果没找到,退栈,用一个变量pos记录下退栈元素的值,下一轮将从pos+1的位置开始寻找,这是因为前面的位置都被试探过了,没必要重新寻找。当栈满时,意味着一种摆放的情况被找到了,此时输出棋盘的状况,退栈,接着寻找其他的摆放方式。当栈空时,意味着所有的情况都被找到,退出循环,程序结束。
运行的流程如下:
while (1)
{
if (s.top == -1)break; //栈空退出循环
if (s.top == MAX_SIZE) { //栈满
//记录解法数目的变量+1
//打印棋盘
pop(s, pos); //退栈 将行号赋给pos
}
for (i = pos + 1; i <= MAX_SIZE; i++) { //从pos+1的位置开始寻找
if (verify(s, row, col)) { //判断位置是否合法 row和col为行号和列号
push(s, i); //将行号入栈
pos = 0; //pos重新置为零
break;
}
}
if (i > MAX_SIZE) { //当i大于最大容量 说明当前列已经没有解了
pop(s, pos); //退栈
}
}
附上完整代码供参考:
#include <iostream>
#include <math.h>
using namespace std;
#define MAX_SIZE 8
typedef struct SqStack {
int row[MAX_SIZE + 1];
int top;
}SqStack;
int count = 0; //记录解法数目
void init_stack(SqStack& s) {
s.top = 0;
s.row[0] = 0;
}
void push(SqStack& s, int e) {
s.top++;
s.row[s.top] = e;
}
void pop(SqStack& s, int& e) {
e = s.row[s.top];
s.top--;
}
//检查位置合法性
int verify(SqStack& s, int row, int col) {
if (col == 1 && row <= 8) return 1; //如果是第一列 返回1
for (int i = 1; i <= col - 1; i++) {
if (s.row[i] == row || (col - i) == abs(row - s.row[i]))
return 0;
}
return 1;
}
//输出棋盘状态
void printChess(SqStack& s) {
cout << "Solution " << ::count << ":";
for (int i = 1; i <= 8; i++) {
cout << s.row[i] << " ";
}
cout << endl;
}
void arrange() {
SqStack s;
init_stack(s);
int i, j;
int pos = 0;
while (1)
{
if (s.top == -1)break; //栈空退出循环
if (s.top == MAX_SIZE) { // 栈满
::count++;
printChess(s);
pop(s, pos);
}
for (i = pos + 1; i <= MAX_SIZE; i++) {
if (verify(s, i, s.top + 1)) {
push(s, i);
pos = 0;
break;
}
}
if (i > MAX_SIZE) {
pop(s, pos);
}
}
}
int main()
{
arrange();
}