8皇后問題

2021-08-26 04:41:46 字數 2432 閱讀 3668

1.問題描述:

在n×n的棋盤上放置n個不能互相捕捉的西洋棋「皇后」的所有布局。這是**於西洋棋中的乙個問題。皇后是棋盤上最具殺傷力的乙個棋子,她可以捕捉與她在同一行,或同一列,或同一斜線(有兩條)上的所有棋子。如下圖所示,紅線經過的格仔都會被皇后捕捉。

2.問題分析:

1)皇后的殺傷力在她所對應的行,列,和兩條斜線上,所以應該滿足該皇后所在的行、列和兩條斜線都不存在其它皇后。

2)所以為了避免皇后衝突,乙個可行的辦法是將棋盤上所有的行,列,和斜線的占用狀態分別用陣列存起來,初始狀態為未占用。在每成功放入乙個皇后以後,將該皇后所對應的行,列,和兩條斜線的狀態更新為占用。在每次嘗試將某個皇后放置到某個位置的時候,需要檢查該位置所對應的行,列,和斜線的占用狀態,只有全部未被占用,才可以將該皇后放到該位置。

3)接下來的問題有兩個:一是如何用陣列來儲存棋盤上所有的行,列,和斜線的占用狀態?二是對棋盤上每乙個位置如何找到它所對應的行、列和斜線在狀態陣列中的位置。以下分行、列、左低右高斜線和左高右低斜線四種情況來討論:

行:對n×n的棋盤有n行(1 ~n),用乙個n + 1維的陣列row[n + 1](row[0]不用)來表示每一行的占用狀態。位置(i,j)對應的行的占用狀態為row[i]。

列:對n×n的棋盤有n列(1 ~n),用乙個n + 1維的陣列col[n + 1](col[0]不用)來表示每一列的占用狀態。位置(i,j)對應的列的占用狀態為col[j]。

左低右高斜線:n×n的棋盤總共有2n – 1條左低右高斜線,所以可以用2n維的陣列b[2n](b[0]不用)來儲存每一條左低右高斜線的占用狀態。。對某一條斜線,其特點是它所經過的每乙個格仔的(列號+ 行號)相等,所以可以用這個值作為陣列下標來唯一標記每一條左低右高斜線,為了使下標從1開始,對所有的下標減1。如下圖所示。位置(i,j)對應的左低右高斜線的占用狀態為b[i + j – 1]。

左高右低斜線:n×n的棋盤總共有2n – 1條左高右低斜線,所以可以用2n維的陣列c[2n](c[0]不用)來儲存每一條左高右低斜線的占用狀態。。對某一條斜線,其特點是它所經過的每乙個格仔的(列號– 行號)相等,所以可以用這個值作為陣列下標來唯一標記每一條左高右低斜線,為了避免出現負值,將所有的下標值都加上乙個n。如下圖所示。位置(i,j)對應的左高右低斜線的占用狀態為c[n + j - i]。

3. 解題思路:

1) 要將n個皇后放到n×n的棋盤中,則每一列必須且只能放乙個皇后。所以問題轉化為確定皇后在每一列中的位置(在第幾行上)。

2) 從第一列開始,依次考察每一列。

3) 在考察每一列的時候,總是從第一行開始,嘗試將皇后放入,如果可以放入,就接著考察下一列的第一行。如果不可以放入,就接著考察這一列的下一行,直到成功,然後接著考察下一列的第一行。

4) 如果這一列的每一行都不可以放入,說明這一列前面各列的皇后放置有問題,導致這一列無法放入,需要回溯。

5) 回溯的時候,如果前面的一列每一行都已經被嘗試過了,就需要接著往前回溯,直到找到還有行未被嘗試過的列,然後嘗試這一列的下一行。

6) 在回溯過程中經過的每一列都需要將已經放入的皇后取出來,以備後面重新選擇位置放入。

7) 如果每一列都被考察完畢,即每一列中的皇后都找到了合適的位置,則找到乙個解。

8) 在找到乙個解後,如果還要尋找其它解,則需要回溯,嘗試其它情況。

9) 當回溯到第0列時,說明1 ~ n列的所有行都已經被嘗試過了,沒有其它情況可以嘗試,結束程式。

4.**:#include using namespace std; void queenlayout(int n); void display(int col,int n); int main() void queenlayout(int n) //初始化所有的斜線為未被占用狀態 for(j=0;j<2*n;j++) do //已經找到乙個解,回溯找下乙個解。 //一直回溯到還有行未被考察過的列 while(col[m]==n) //考察這一列的下一行 col[m]++; } else } else //考察這一列的下一行 col[m]++; } //考察皇后是否可以被放在當前考察列的當前考察行,即她對應的行和兩條斜線是否全部未被占用 occupied=row[col[m]] || b[m+col[m]-1] || c[n+m-col[m]]; }while(m!=0);//退到m == 0, 表示 1 ~ n 列的所有行都被考察過了,即考察過了所有可能的情況,整個考察過程結束。 delete row; delete col; delete b; delete c; } void display(int col,int n) { char **map=new char*[n]; for(int i=0;i一部分測試結果

8皇后問題

會下西洋棋的人都很清楚 皇后可以在橫 豎 斜線上不限步數地吃掉其他棋子。如何將8個皇后放在棋盤上 有8 8個方格 使它們誰也不能被吃掉!這就是著名的八皇后問題。對於某個滿足要求的8皇后的擺放方法,定義乙個皇后串a與之對應,即a b1b2.b8,其中bi為相應擺法中第i行皇后所處的列數。已經知道8皇后...

8皇后問題

8 皇后問題 描述 八皇后問題是大數學家高斯於1850年提出來的。該問題是在8 8的西洋棋棋盤上放置8個皇后,使得沒有乙個皇后能 吃掉 任何其他乙個皇后,即沒有任何兩個皇后被放置在棋盤的同一行 同一列或同一斜線上。輸出8皇后問題所有結果。輸入 沒有輸入。輸出 每個結果第一行是no n 的形式,n表示...

8皇后問題

8皇后問題 在乙個8 8的棋盤上如何安置8個皇后 不允許任何兩個皇后在同一列,同一行,同一斜線 斜率為正負一 思路 用一維陣列的下標和值表示 皇后的座標 0,0 7,7 例如a 1 0,表示 1,0 暴力8的8次方種情況,用二進位制表示,即00000000 77777777 十進位制表示0 pow ...