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...