跳至內容

八皇后問題

維基百科,自由的百科全書

這是本頁的一個歷史版本,由Lijt931留言 | 貢獻2018年11月4日 (日) 01:13編輯。這可能和目前版本存在著巨大的差異。

abcdefgh
8
f8 white queen
d7 white queen
g6 white queen
a5 white queen
h4 white queen
b3 white queen
e2 white queen
c1 white queen
8
77
66
55
44
33
22
11
abcdefgh
八皇后問題的唯一對稱解(不包括旋轉和反射變換)

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

歷史

八皇后問題最早是由西洋棋棋手馬克斯·貝瑟爾(Max Bezzel)於1848年提出。第一個解在1850年由弗朗茲·諾克(Franz Nauck)給出。並且將其推廣為更一般的n皇后擺放問題。諾克也是首先將問題推廣到更一般的n皇后擺放問題的人之一。

在此之後,陸續有數學家對其進行研究,其中包括高斯康托,1874年,S.岡德爾提出了一個通過行列式來求解的方法[2],這個方法後來又被J.W.L.格萊舍加以改進。

1972年,艾茲格·迪傑斯特拉用這個問題為例來說明他所謂結構化編程的能力[3]。他對深度優先搜索回溯算法有著非常詳盡的描述2

八皇后問題在1990年代初期的著名電子遊戲第七訪客NDS平台的著名電子遊戲《雷頓教授與不可思議的小鎮》中都有出現。

解題方法

八個皇后在8x8棋盤上共有4,426,165,368(64C8)種擺放方法,但只有92個互不相同的解。如果將旋轉和對稱的解歸為一種的話,則一共有12個獨立解,具體如下:

解的個數

下表給出了n皇后問題的解的個數包括獨立解U(OEIS數列A002562)以及互不相同的解D(OEIS數列A000170)的個數:

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 1,787 9,233 45,752 ..
D 1 0 0 2 10 4 40 92 352 724 2,680 14,200 73,712 365,596 ..

可以注意到六皇后問題的解的個數比五皇后問題的解的個數要少。現在還沒有已知公式可以對n計算n皇后問題的解的個數。

示例程序

下面是求解n皇后的C代碼,在程序中可以自己設置n個皇后以及選擇是否列印出具體解。

#include <stdio.h>

#define QUEENS       8 /*皇后数量*/
#define IS_OUTPUT    1 /*(IS_OUTPUT=0 or 1),Output用于选择是否输出具体解,为1输出,为0不输出*/

int A[QUEENS + 1], B[QUEENS * 3 + 1], C[QUEENS * 3 + 1], k[QUEENS + 1][QUEENS + 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[i][j] = a[j] = b[j - i] = c[j + i] = 1;
      if (i < QUEENS) lay(i + 1);
      else {
        ++inc;
        if (IS_OUTPUT) {
          for (printf("(%d)\n", inc), u = QUEENS + 1; --u; printf("\n"))
            for (t = QUEENS + 1; --t; ) k[t][u] ? printf("Q ") : printf("+ ");
          printf("\n\n\n");
        }
      }
      a[j] = b[j - i] = c[j + i] = k[i][j] = 0;
    }
}

int main(void) {
  lay(1);
  printf("%d皇后共计%d个解\n", QUEENS, inc);
  getchar();
  return 0;
}

以下列出尼克勞斯·維爾特Pascal語言程序[4]。此程序找出了八皇后問題的一個解。

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[ i]:4);
writeln
end.

參考資料

  1. ^ Watkins, John J. (2004). Across the Board: The Mathematics of Chess Problems. Princeton: Princeton University Press. ISBN 0-691-11503-6
  2. ^ W. W. Rouse Ball英語W. W. Rouse Ball (1960) The Eight Queens Problem, in Mathematical Recreations and Essays, Macmillan, New York, pp 165-171.
  3. ^ 奧利-約翰·達爾, 艾茲赫爾·戴克斯特拉, 東尼·霍爾 Structured Programming, Academic Press, London, 1972 ISBN 0-12-200550-3 see pp 72-82 for Dijkstra's solution of the 8 Queens problem.
  4. ^ Wirth, 1976, p. 145