回溯 N皇后問題

2021-08-21 15:21:40 字數 1738 閱讀 7347

會下西洋棋的人都很清楚:皇后可以在橫、豎、斜線上不限步數地吃掉其他棋子。如何將8個皇后放在棋盤上(有8 * 8個方格),使它們誰也不能被吃掉!這就是著名的八皇后問題。 對於某個滿足要求的8皇后的擺放方法,定義乙個皇后串a與之對應,即a=b1b2…b8,其中bi為相應擺法中第i行皇后所處的列數。已經知道8皇后問題一共有92組解(即92個不同的皇后串)。給出乙個數b,要求輸出第b個串。串的比較是這樣的:皇后串x置於皇后串y之前,當且僅當將x視為整數時比y小。 

輸入資料

第1行是測試資料的組數n,後面跟著n行輸入。每組測試資料佔1行,包括乙個正整數b(1 <= b <= 92)

輸出要求

n行,每行輸出對應乙個輸入。輸出應是乙個正整數,是對應於b的皇后串

輸入樣例21

92輸出樣例

15863724

84136275

分析:從n×n個格仔中選擇n個格仔擺放皇后。可見解空間樹為子集樹。

使用maze[max][max]來表示棋盤,maze[i][j]=0 表示(i,j)位置為空,maze[i][j]=1 表示(i,j)位置擺放有乙個皇后。

全域性變數way表示總共的擺放方法數目。

使用queen(t)來擺放第t個皇后。queen(t) 函式符合子集樹時的遞迴回溯正規化。當t>n時,說明所有皇后都已經擺   放完成,這是乙個可行的擺放方法,輸出結果;否則,遍歷棋盤,找皇后t所有可行的擺放位置,placequeen(i,j) 判斷皇后t能否擺放在位置(i,j)處,如果可以擺放則繼續遞迴擺放皇后t+1,如果不能擺放,則判斷下乙個位置。

placequeen(row,col)函式首先判斷位置(row,col)是否合法,繼而判斷(row,col)處是否已有皇后,有則衝突,返回0,無則繼續判斷行、列、斜方向是否衝突。斜方向分為左上角、左下角、右上角、右下角四個方向,每次從(row,col)向四個方向延伸乙個格仔,判斷是否衝突。如果所有方向都沒有衝突,則返回1,表示此位置可以擺放乙個皇后。

**:

#include#include#include# define max  4

int maze[max][max];//棋盤 0表示空白 1表示有皇后

int placequeen(int row, int col){

int i,j;

if(maze[row][row] == 1)

return 0;

for(j=0; j= 0) && (col-i >= 0))

if(maze[row-i][col-i] == 1)

return 0;

for(i=1; i= 0) && (col+i < max))

if(maze[row-i][col+i] == 1)

return 0;

for(i=1; i= 0))

if(maze[row+i][col-i] == 1)

return 0;

for(i=1; imax){//放置完成

printf("完成一次配置\n");

for(int i=0; i該問題還有更優的解法。充分利用問題隱藏的約束條件:每個皇后必然在不同的行(列),每個行(列)必然也只有乙個皇后。這樣我們就可以把n個皇后放到n個行中,使用pos[i]表示皇后i在i行中的位置(也就是列號)(i = 0 to n-1)。這樣**會大大的簡潔,因為節點的子節點數目會減少,判斷衝突也更簡單。

回溯 n皇后問題

思想 用回溯方法求解,首先要分析問題的求解空間。可用一棵n叉樹表示這個問題的求解空間,在回溯遍歷這個課二叉樹的過程中形成合理的解。對於這棵n叉樹,列序號i 0 n 1 是它的孩子,而每個孩子都有深度為n的子樹 包括自身 這些子樹的層次是n個皇后 也代表每個皇后的行序號,因為不同的皇后肯定不在同一行 ...

n皇后問題(回溯)

problem description 在n n的方格棋盤放置了n個皇后,使得它們不相互攻擊 即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。你的任務是,對於給定的n,求出有多少種合法的放置方法。input 共有若干行,每行乙個正整數n 10,表示棋盤和皇后的數量 如...

回溯經典 n皇后問題

題目大意 八皇后問題是乙個以西洋棋為背景的問題 如何能夠在 8 8 的西洋棋棋盤上放置八個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處於同一條橫行 縱行或斜線上。八皇后問題可以推廣為更一般的n皇后擺放問題 這時棋盤的大小變為n n,而皇后個數也變成n。當且僅當 ...