// n queens problem
// 試探-回溯演算法,遞迴實現
// sum用來記錄皇后放置成功的不同布局數;upperlim用來標記所有列都已經放置好了皇后。
long sum = 0, upperlim = 1;
// 試探演算法從最右邊的列開始。
void test(long row, long ld, long rd) 。
}else
}int main(int argc, char *argv)
printf("%d 皇后/n", n);
// n個皇后只需n位儲存,n列中某列有皇后則對應bit置1。
upperlim = (upperlim << n) - 1;
test(0, 0, 0);
printf("共有%ld種排列, 計算時間%d秒 /n", sum, (int) (time(0) - tm));
}上述**容易看懂,但我覺得核心的是在針對試探-回溯演算法所用的資料結構的設計上。
程式採用了遞迴,也就是借用了編譯系統提供的自動回溯功能。
演算法的核心:使用bit陣列來代替以前由int或者bool陣列來儲存當前格仔被占用或者說可用資訊,從這
可以看出n個皇后對應需要n位表示。
巧妙之處在於:以前我們需要在乙個n*n正方形的網格中挪動皇后來進行試探回溯,每走一步都要觀察
和記錄乙個格仔前後左右對角線上格仔的資訊;採用bit位進行資訊儲存的話,就可以只在一行格仔也
就是(1行×n列)個格仔中進行試探回溯即可,對角線上的限制被化歸為列上的限制。
程式中主要需要下面三個bit陣列,每位對應網格的一列,在c中就是取乙個整形數的某部分連續位即可
。row用來記錄當前哪些列上的位置不可用,也就是哪些列被皇后占用,對應為1。
ld,rd同樣也是記錄當前哪些列位置不可用,但是不表示被皇后占用,而是表示會被已有皇后在對角線
上吃掉的位置。這三個位陣列進行「或」操作後就是表示當前還有哪些位置可以放置新的皇后,對應0
的位置可放新的皇后。如下圖所示的8皇后問題求解得第一步:
row: [ ][ ][ ][ ][ ][ ][ ][*]
ld: [ ][ ][ ][ ][ ][ ][*][ ]
rd: [ ][ ][ ][ ][ ][ ][ ][ ]
------------------------------------
row|ld|rd: [ ][ ][ ][ ][ ][ ][*][*]
所有下乙個位置的試探過程都是通過位操作來實現的,這是借用了c語言的好處,詳見**注釋。
**編寫 hai1039
*/
n皇后 位運算版
n皇后問題是大家在遞迴裡會碰到的乙個經典問題。以前高中我學dfs的時候,老師首先讓我看的就是八皇后。不過這皇后的時間複雜度大家可想而知了。而接下來的位運算將這個效率重新提到乙個高度。我是以前在matrix67大牛那裡學的,最近資料結構實驗剛好碰到n皇后,就在這裡 複述 一遍吧。code void d...
八皇后問題擴充套件版 c
任意大小棋盤,任意數量的皇后 include include using namespace std const int num 8 方形棋盤行數 const int qnum 8 加入皇后的個數 int a num 1 存放棋盤資訊的陣列,陣列號代表行號,對應陣列值代表列號 static int ...
演算法 位運算 與 n皇后問題
問題a 返回n皇后擺法有多少種?遞迴函式,維護三個變數和乙個常量 常量 upperlim 代表棋盤大小,末尾n個1,例如八皇后,00 011111111 變數 顯然,遞迴函式的跳出條件為,nowlim upperlim 其中每層遞迴函式,可以通過位運算快速找到可以擺放的位置。pos upperlim...