八皇后問題(回溯演算法)

2021-07-02 15:20:56 字數 2108 閱讀 7476

八皇后問題是古老的問題,十八世紀由乙個西洋棋手提出的,即在乙個8 * 8 的西洋棋盤上,放置八個皇后,使它們不能相互攻擊到。即不能處於同一行,同一列,也不能處於同一條斜線上,問有多少種擺法。八皇后問題是經典的回溯演算法問題,後人利用計算機,算出了8 * 8 的棋盤上能擺出92種,而後又提出了n皇后問題。

本人不太擅長演算法,弄了幾天,才弄懂這個演算法,並且把自己對回溯的學習記錄下來。

首先看看題目說的,需要n * n的棋盤上放置n 個皇后,其在某個位置a (x, y)是否安全的判斷為,對於所有已擺放的皇后位置b (x, y), ∀b(i) ,

有 b(i).x ≠ a.x ∧ b(i).y ≠ a.y 表示不在同一列,同一行;

有 b(i).x + b(i).y ≠ a.x + a.y 表示不在同一條斜線(右上到左下方向)上;

有 b(i).x - b(i).y ≠ a.x - a.y 表示不在同一條斜線(左上到右下方向)上;

而且每放下乙個皇后,就要判斷所有已放置的皇后位置是否能攻擊到,那麼我們需要乙個儲存空間來儲存所有已放置的皇后位置資訊,進行迭代,

可以選用陣列,也可以選用矩陣;但我們大可不用矩陣,畢竟棋盤是n * n 的,且每個皇后不可能在同一行擺放,或者不可能再同一列擺放,於是只使用乙個一維

陣列,便能儲存八皇后位置。我們定義陣列queen (n)的乙個下標索引x ∈(0,1,2..n-1)表示棋盤的某一列,那麼其值queen (x) 即儲存乙個皇后在此列中哪一行擺放。

接著分析一下演算法流程:

當我們放置乙個皇后時迭代此列上所有的行,且所有的行都要測試,以便我們找的所有的解。

當某行測試通過時,可以繼續迭代下一列的皇后擺放位置,直到列標為n-1,此時即可確定一種擺放方法。;

當某一行測試不通過時,繼續下一行的迭代,直到行標為n-1。

如此進行回溯,直到所有的解空間樹都被遍歷一遍。

全域性變數:

_n 表示使用者輸入的棋盤大小,預設為8.

queen 用於儲存n個皇后的位置,由 _n 確定大小。

maxnum 用於儲存找到的所有解數。

函式:主要的回溯函式為loop (),傳入引數表示從_sta_col這一列開始放置後面的皇后,當放置到最後n-1列並檢測安全後(此時會再次遞迴呼叫loop (n)),返回true,否則返回false,繼續進行迭代。

check () 函式用於檢測已放置的皇后與放置在引數(_row, _col)處的皇后是否有衝突,有則返回false,表示不安全。

main () 只做簡單的使用者輸入處理,並進行一定初始化,之後呼叫loop (),從0列開始計算。

命令格式: main , 引數n > 0。

/*

author : yez

date : 2015/5/17

describe : eight queen algorithm

*/#include #include #include #include // default value

int _n = 8;

int* queen;

int maxnum = 0;

bool loop (int);

bool check (int, int);

bool loop (int _sta_col)

for (; i < _n; i ++)

} return false;

} bool check (int _row, int _col)

return true;

}int main (int argc, char* argv )

} queen = (int*) malloc (sizeof (int) * _n);

memset (queen, 0, sizeof (int) * _n); // memory.h

loop (0);

printf ("n = %d, %d\n", _n, maxnum);

return 0;

}

編譯環境:

linux x86_64

gcc (ubuntu/linaro 4.6.3-1ubuntu5) 4.6.3

gdb (ubuntu/linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04

八皇后問題 回溯演算法

最近學習了一下列舉演算法,有兩種思路,遞迴構造和直接列舉。直接列舉的優點就是思路和程式很簡潔,缺點就在於無法簡便的減少列舉量,必須生成所有的解並進行判斷。遞迴構造就很簡單了,在生成列舉量的同時並且可以通過判斷減少列舉量從而達到了數量上的減少。簡單的說,直接列舉就是先找尋解再判斷,遞迴構造則是先判斷再...

回溯演算法 八皇后問題

問題描述 八皇后不能相互攻擊,即,八個皇后不能同行,同列,不同在同一條對角線上,對角線又可以分為左對角線和右對角線 左對角線上滿足 i j 7都相等 i,j分別是一維和二維的座標 右對角線滿足 i j 都相等 如下 include using namespace std int e q 8 8 in...

八皇后問題(回溯演算法)

八皇后問題,是乙個古老而著名的問題,是回溯演算法的典型案例。該問題是國際西洋棋棋手馬克斯 貝瑟爾於1848年提出 在8 8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。高斯認為有76種方案。1854年在柏林的象棋雜誌上不同的作者發表了...