在n×n格的西洋棋上擺放n個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。八皇后如下圖所示。八皇后問題是一道經典的dfs回溯問題,一開始先將第0行第0列的位置放入皇后1(使用習慣,有大佬習慣以1開始也乙個道理),那麼在第0行所有的位置和第0列所有的位置以及其對角線上都不可能再有皇后。
我們一開始選擇(0,0)點(即第一行第乙個位置)安置皇后1,則下乙個皇后(皇后2)一定不在這一行我們就可以直接從(1,0)點(第二行第乙個位置)位置開始窮舉。當然,第二行第乙個位置和第二行第二個位置肯定都是不可以的了,因為他們不是和第乙個皇后在一列就是和第乙個皇后在同乙個對角線。
要做這道題一定要明確兩個問題。
何時進行輸出?
如何進行標記?
對於問題一,還是比較簡單的,在進行dfs時傳遞乙個引數表示當前行,當當前行數等於n的時候就進行輸出(因為我是以0開始的)。
對於問題二,這就是乙個數學問題了,如下表所示,標出座標:01
230(0,0)
(0,1)
(0,2)
(0,3)
1(1,0)
(1,1)
(1,2)
(1,3)
2(2,0)
(2,1)
(2,2)
(2,3)
3(3,0)
(3,1)
(3,2)
(3,3)
我們以紅色座標(1,2)為例,則可以發現與它同一列的座標都是以2結尾的(綠色部分);主對角線上(左上到右下)的縱座標與橫座標的差都是固定值1(橙色部分);副對角線上的縱座標與橫座標的和是固定值3(紫色部分);由此我們可以得出由此推出一般結論也是如此。
我們可以設計乙個儲存結構來判定每一列、每一對角線上是否還可以放置皇后。可以使用3個一維陣列,也可以使用乙個三行2*n列的二維陣列,為什麼是2*n我們一會兒再說。
下面我們開始解題。
設題中n的值為n;剛才遺留的二維陣列的第二維為什麼是n*2?pos[p]=q表示在第p行第q列放置皇后;
mark[i][j]:為布林型別的標記陣列,預設false,當i=0且值為true時,表示第j列已被標記,無法放置皇后,
當i=1且值為true時,表示縱座標與橫座標之和為定值j的座標已被標記,即副對角線,
當i=2且值為true時,表示縱座標與橫座標之差為定值j-n的座標已被標記,即主對角線;
為什麼mark陣列當i=2時,縱座標與橫座標之差要加上n?
對於問題一,若是4皇后問題,則最大的橫縱座標值和為3 + 3 = 6,為了不浪費空間我們選擇n*2;
對於問題二,我們之前**過,主對角線上縱座標與橫座標之差是定值,但可能是負數,而我們知道,陣列的下標是不能為負數的,所以我們將其加上n,乙個定值加上乙個定值,既保證了它仍是定值,也保證了它是正數。同樣以4皇后為例,最壞的情況是座標(3,0),0 - 3 = -3,再加上4等於1,為正數(這裡感謝陳梓軒大佬)。
我們這裡輸出每一種可能的情況與總的情況數量,測試**如下處理對角線是重點,其他就是基本的dfs思路。/**
* 全域性變數如下
*/int n = 0;
int tot = 0;
int pos;
boolean mark;
/** * cur為當前行,開始傳入的是0
*/public void dfs(int cur) else
}system.out.println();
} system.out.println();
this.tot++;
}else
} }}
@test
public void nqueens()
N皇后問題
include define maxqueens 20 define minqueens 4 enum bool typedef struct queendata queendata queendata queens maxqueens 1 int ncount init int init chec...
N皇后問題
採用遞迴回溯法 執行結果 輸入8 對於n皇后解的個數,參考 當n 16時,構造法給出解,參考poj 3239 一 當n mod 6 2 且 n mod 6 3時,有乙個解為 2,4,6,8,n,1,3,5,7,n 1 n為偶數 2,4,6,8,n 1,1,3,5,7,n n為奇數 上面序列第i個數為...
N皇后問題
問題 題目 於西洋棋的玩法,因為皇后所在的位置可以縱向 橫向 兩個斜向四個方向的 捕捉 所以8皇后問題就是要求如何布置8個皇后在8 8的棋盤上而使他們互相無法 捕捉 也就是說不存在兩個皇后同行或同列,或在同一斜線上。而n皇后問題就是如何布置n個皇后在n n棋盤裡使不存在兩個皇后在同行同列和同一斜線上...