八皇后問題

2021-05-28 06:30:31 字數 2853 閱讀 1645

1.

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

問題分析: 1)

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

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

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

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

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

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

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

解題思路: 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

八皇后問題

八皇后問題 ackarlix 八皇后問題是乙個古老而著名的問題,是回溯演算法的典型例題。該問題是十九世紀著名的數學家高斯 1850 年提出 在 8x8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。高斯認為有 76種方案。1854 年在...

八皇后問題

include iostream.h int a 8 8 棋盤 int r 8 結果 int i,j int count 0 void init i j 0 int judge int x,int y for int mi x 1,mj y mi 1 mi for int ri x 1,rj y 1...

八皇后問題

package quess 由於八個皇后的任意兩個不能處在同一行,那麼這肯定是每乙個皇后佔據一行。於是我們可以定義乙個陣列columnindex 8 陣列中第i個數字表示位於第i行的皇后的列號。先把columnindex的八個數字分別用0 7初始化,接下來我們要做的事情就是對陣列columninde...