關於N皇后問題高效試探回溯演算法的分析

2021-04-20 19:58:32 字數 1446 閱讀 5548

// 試探-回溯演算法,遞迴實現

// 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語言的好處,詳見**注釋。

關於此演算法,如果考慮n×n棋盤的對稱性,對於大n來說仍能較大地提公升效率!

關於N皇后問題高效試探回溯演算法的分析

n queens problem 試探 回溯演算法,遞迴實現 sum用來記錄皇后放置成功的不同布局數 upperlim用來標記所有列都已經放置好了皇后。long sum 0,upperlim 1 試探演算法從最右邊的列開始。void test long row,long ld,long rd els...

試探回溯法(N皇后問題)

然後影響速度的主要是函式中的checkout函式,我使用的是遍歷棧中所有皇后元素與當前皇后元素比對的方式,在棧中資料量龐大是時候似乎效率略低,這樣導致我的函式在計算n 9,10之類的方格時已需要數秒時間。然而鄧公的dsacpp中用的是vector繼承的find函式,相對來說速度比我的快一點,不過基本...

用試探回溯法解決N皇后問題

學校資料結構的課程實驗之一。資料結構 其實只用了乙個二維陣列 演算法 深度優先搜尋,試探回溯 需求分析 設計乙個在控制台視窗執行的 n皇后問題 解決方案生成器,要求實現以下功能 由n n個方塊排成n行n列的正方形稱為n元棋盤。如果兩個皇后位於n元棋盤上的同一行 同一列或同一對角線上,則稱它們在互相攻...