兩種不同方式解決八皇后問題
阿新 • • 發佈:2019-01-02
問題描述
八皇后問題是一個以國際象棋為背景的問題:如何能夠在8×8的國際象棋棋盤上放置八個皇后,使得任何一個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處於同一條橫行、縱行或斜線上。
解決思路
這個問題可以有兩種解決方法,一種是使用遞迴,比較簡單易懂,另一種是使用棧,利用棧的特性避免了遞迴的使用,從而提高了效率(遞迴的雖然簡單易寫,但是其效率往往較低)。
具體實現
首先將節點的座標定義為結構體:
typedef struct {
int x;
int y;
} Coord;
定義好judge函式(用於判斷對應點座標是否可以放置皇后):
bool judge(SqStack S, int x, int y) { SqStack m = S; while (!StackEmpty(m)) { Coord e; e = Pop(m); if ((e.x == x) || (abs(e.x - x) == abs(e.y - y))) { return false;//如果不行返回false } } return true;//如果可以返回true }
遞迴
void Recursive(SqStack &S, int y) { if (StackEmpty(S)) { for (int i = 1; i <= N; ++i) { Coord e; e.x = i; e.y = 1; Push(S, e); Recursive(S, 2); Pop(S); } } else if (Full(S)) { StackTraverse(S); n++; return; } else { for (int i = 1; i <= N; ++i) { if (judge(S, i, y)) { Coord e; e.x = i; e.y = y; Push(S, e); Recursive(S, y + 1); Pop(S); } } } }
這裡要注意遞迴呼叫Recurive之後要pop出遞迴之前push進去的,有進就要有出~
非遞迴
void Search(SqStack s) { int i = 1; bool flag; Coord e; e.x = 0; e.y = 1; while (i <= 8) { if (flag) { e.x = 0; } if (Full(s)) { e = Pop(s); } flag = false; for (int j = e.x + 1; j <= 8; j++) { if (judge(s, j, i)) { Coord e2; e2.x = j; e2.y = i; Push(s, e2); // cout << "a" << i << "(" << e.y << "," << e.x << ") "; flag = true; break; } } if (flag) { if (i == 8) { StackTraverse(s); num++; } else { i++; } } else { i--; e = Pop(s); if (i == 0) { break; } } } }