八皇后問題是一個以國際象棋為背景的問題：如何能夠在 88 的國際象棋棋盤上放置八個皇后，使得任何一個皇后都無法直接吃掉其他的皇后？為了達到此目的，任兩個皇后都不能處於同一條橫行、縱行或斜線上。八皇后問題可以推廣為更一般的 n 皇后擺放問題：這時棋盤的大小變為 nn，而皇后個數也變成 n。當且僅當 n 1 或 n 4 時問題有解 Watkins John J 2004 Across the Board The Mathematics of Chess Problems Princeton Princeton University Press ISBN 0691115036。 歷史 八皇后問題最早是由西洋棋棋手馬克斯貝瑟爾（Max Bezzel）於 1848 年提出。第一個解在 1850 年由弗朗茲諾克（Franz Nauck）給出。並且將其推廣為更一般的 n 皇后擺放問題。諾克也是首先將問題推廣到更一般的 n 皇后擺放問題的人之一。 在此之後，陸續有數學家對其進行研究，其中包括高斯和康託，1874 年，S 岡德爾提出了一個透過行列式來求解的方法 1960 The Eight Queens Problem in Mathematical Recreations and Essays Macmillan New York pp 165171，這個方法後來又被 JWL 格萊舍加以改進。 1972 年，艾茲格迪傑斯特拉用這個問題為例來說明他所謂結構化程式設計的能力奧利 約翰達爾，艾茲赫爾戴克斯特拉，東尼霍爾 Structured Programming Academic Press London 1972 ISBN 0122005503 see pp 7282 for Dijkstras solution of the 8 Queens problem。他對深度優先搜尋回溯演算法有著非常詳盡的描述 2。 八皇后問題在 1990 年代初期的著名電子遊戲《第七訪客》和 NDS 平臺的著名電子遊戲《雷頓教授與不可思議的小鎮》中都有出現。 解題方法 八個皇后在 8x8 棋盤上共有 4426165368（64C8）種擺放方法，但只有 92 個可行（皇后間互不攻擊）的解。如果將旋轉和對稱的解歸為一種的話，則一共有 12 個獨立解，具體如下： 解的個數 下表給出了 n 皇后問題的解的個數包括獨立解 U 以及可行解 D 的個數： n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 U 1 0 0 1 2 1 6 12 46 92 341 1787 9233 45752 D 1 0 0 2 10 4 40 92 352 724 2680 14200 73712 365596 可以注意到六皇后問題的解的個數比五皇后問題的解的個數要少。現在還沒有已知公式可以對 n 計算 n 皇后問題的解的個數。 示例程式 下面是求解 n 皇后的 C 程式碼，在程式中可以自己設定 n 個皇后以及選擇是否打印出具體解。 include stdioh define QUEENS 8 皇后數量 define IS_OUTPUT 1 IS_OUTPUT0 or 1，Output 用於選擇是否輸出具體解，為 1 輸出，為 0 不輸出 int A QUEENS 1 B QUEENS 3 1 C QUEENS 3 1 k QUEENS 1QUEENS 1 int inc a A b B QUEENS c C void lay int i int j 0 t u while j QUEENS if a j b j i c j i 0 k ij a j b j i c j i 1 if i QUEENS lay i 1 else inc if IS_OUTPUT for printf dn inc u QUEENS 1 u printf n for t QUEENS 1 t k tu printf Q printf printf nnn a j b j i c j i k ij 0 int main void lay 1 printf d 皇后共計 d 個解 n QUEENS inc return 0 以下列出尼克勞斯維爾特的 Pascal 語言程式 Wirth 1976 p 145。此程式找出了八皇后問題的一個解。 program eightqueen1 output var i integer q boolean a array 1 8 of boolean b array 2 16 of boolean c array 7 7 of boolean x array 1 8 of integer procedure try i integer var q boolean var j integer begin j 0 repeat j j 1 q false if a j and b i j and c i j then begin x i j a j false b i j false c i j false if i 8 then begin try i 1 q if not q then begin a j true b i j true c i j true end end else q true end until q or j 8 end begin for i 1 to 8 do a i true for i 2 to 16 do b i true for i 7 to 7 do c i true try 1 q if q then for i 1 to 8 do write x i4 writeln end 使用回溯法進行求解八皇后問題 includestdioh define PRINTF_IN 1 定義是否列印，1：列印，0：不列印 int queens int Queens int i k flag not_finish1 count0 正在處理的元素下標，表示前 i1 個元素已符合要求，正在處理第 i 個元素 int a Queens1 八皇后問題的皇后所在的行列位置，從 1 幵始算起，所以加 1 i1 a 11 為陣列的第一個元素賦初值 printf d 皇后的可能配置是Queens while not_finish not_finishl 處理尚未結束 while not_finish iQueens 處理尚未結束且還沒處理到第 Queens 個元素 for flag1k1 flag k1 a iQueens a i1 當 a i 為 Queens 時將 a i 的值置 1 else if i1 a iQueens not_finish0 當第一位的值達到 Queens 時結束 else a i 將 a il 的值取下一個值 else if a i Queens a i1 else a i 將 a i 的值取下一個值 else if iQueens if a i1 Queens a i1 若前一個元素的值為 Queens 則 a il else a i a i11 否則元素的值為前一個元素的下一個值 if not_finish count if PRINTF_INprintf count13 2d n 2d count for k1 kQueens k 輸出結果 printf d a k if a Queens1Queens a Queens1 修改倒數第二位的值 else a Queens11 iQueens 1 開始尋找下一個滿足條件的解 return count int main int Num printf 輸入一個 N 皇后數值： scanf d Num printf n d 皇后有 d 種配置 nNumqueens Num 使用回溯法進行求解八皇后問題 Java 版本，可直接複製到 NQueens LeetCode 測試。 class Solution public ListListString solveNQueens int n ListListString results new ArrayList 使用 char 是為了展示結果時，直接使用 new String char 。 一般情況下，使用 boolean 即可。 char result new char nn for int i 0 i n i for int j 0 j n j result ij backtrack results result 0 return results private static void backtrack ListListString results char result int x for int j 0 j resultlength j if isValid result x j result xj Q if x resultlength 1 showResult results result 可以直接 break else 皇后問題中，不會出現一行出現多個，所以直接跳到下一行 backtrack results result x 1 result xj private static boolean isValid char result int x int y 0 y x1 y x y for int i 0 i x i if result iy Q return false x1 y1 x y for int i x 1 j y 1 i 0 j 0 i j if result ij Q return false x1 y1 x y for int i x 1 j y 1 i 0 j resultlength i j if result ij Q return false return true private static void showResult ListListString results char result ListString list new ArrayListresultlength for char value result listadd new String value resultsadd list include iostream include cmath using namespace std define Max 20 定義棋盤的最大值 int a Max int show int S 定義出函式 int ipq int b MaxMax0 定義且初始化 b 1 輸出模組 for i1iSi 按橫列順序輸出 a i 的座標 b ia i1 printf d dtia i printf n for p1pSp 按棋盤的橫列的順序標明的位置 for q1qSq if b pq1 在第 p 行第 q 列放置一顆棋子 printf x else printf o printf n return 0 int check int k 定義 check 函式 int i for i1iki if a ia k a ia kki a ia kik 檢查是否有多顆棋子在同一個直行上 return 0 return 1 void check_m int num 定義函式 int k1count0 printf N 皇后問題的所有解 包含經由旋轉的解n a k1 while k0 if knum a knum 從第 k 行第一列的位置開始，尋找之後的棋子的位置 if check k0 第 k 行的 a k 列不能放置棋子 a k 繼續試探該前行的下一列：a k1 else k 第 K 行的位置已經確定完畢，繼續尋找第 k1 行棋子的位置 a k1 從第 k1 的第一列開始查詢 else if knum 若滿足輸出陣列的要求就輸出該陣列 count printf dcount show num 呼叫輸出函式 show k 棋子位置不符合要求則退回前一步 a k 繼續尋找下一列位置 printf 總共有 d ncount個 int main void int Nd do printf N 皇后問題的解 N20 n printf 請輸入 N 的值：_ scanf dN printf n if N0N20 check_m N break else printf 輸入錯誤，請重新輸入 printf nn break while 1 system pause return 0 大眾文化 電腦遊戲《第七訪客》中，伊格（Ego，玩家）在史陶夫的府邸的遊戲室裡碰到的象棋問題正是八個皇后問題。 延伸閱讀 OJ Dahl E W Dijkstra C A R Hoare Structured Programming Academic Press London 1972 see pp 7282 for Dijkstras solution of the 8 Queens problem On The Modular NQueen Problem in Higher Dimensions Ricardo Gomez Juan Jose Montellano and Ricardo Strausz 2004 Instituto de Matematicas Area de la Investigacion Cientifica Circuito Exterior Ciudad Universitaria Mexico 參考資料 Category 數學西洋棋問題 Category 組合數學 Category 組合計數 Category 下棋問題