【8-8】皇后是西洋棋中威力最大的棋子,在下面所示的棋盤上,皇后可以攻擊位於箭頭所覆蓋位置的所有棋子。
我們能不能把8個皇后放在棋盤上,它們中任何乙個都無法攻擊其餘的皇后?這個問題被稱為八皇后問題,你的任務是編寫乙個程式,找到八皇后問題的所有答案,看看一共有多少種答案。
這個題目是對回溯法的考察,難度5顆星,各大刷題**和面試**現經常出現,所以必須掌握。題目也給出了基本的演算法思路。
回溯法(探索與回溯法)是一種選優搜尋法,又稱為試探法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態的點稱為「回溯點」。這裡先把規則理出來: 皇后不能同列,不能同行,不能在對角線上。
首先把皇后放在第一行第一列,然後遍歷這個皇后固定在第一行第一列後的所有解;第一行不需要校驗上半部分的衝突,所以直接放置。然後再將第一行第一列的那個皇后固定在第一行第二列,再次遍歷完所有解;
直到 第一行的皇后放在最後一列,遍歷完所有的解。
固定皇后在[0][0]位置:
判斷第1行哪些列可以放置皇后,放置皇后
判斷第2行哪些列可以放置皇后,放置皇后
判斷第3行哪些列可以放置皇后,放置皇后
判斷第4行哪些列可以放置皇后,放置皇后
判斷第5行哪些列可以放置皇后,放置皇后
判斷第6行哪些列可以放置皇后,放置皇后
判斷第7行哪些列可以放置皇后,放置皇后
其他地依次類推
所以這個邏輯就可以描述為:
for(column = 0; column < 8; column++)
//有衝突無法放置
board[row][column] = false;
}
可以看到這裡有乙個繼續向下放置皇后,每一行放置後就需要繼續放置下一行的皇后,而且放置邏輯都是一樣,只是行數不一樣,所以很容易就可以想到遞迴。
void place_queen(int row)
//有衝突無法放置
board[row][column] = false;
}}
判斷衝突抽象為乙個函式:
判斷當前校驗的位置的同列上面有無放置皇后,所以這個衝突檢測行數可以抽象為:判斷同行左側和右側有無放置皇后,
判斷左上部分和右上部分的對角線有無放置皇后
//檢測board[row][column]的上半部分的方向上是否有其他皇后
int conflicts(int row, int column)
return 0;
}
完整**如下:
#define true 1
#define false 0
int board[8][8];
//列印解決方案
void print_board()
putchar('\n');
}putchar('\n');
}//檢測board[row][column]的上半部分的方向上是否有其他皇后
int conflicts(int row, int column)
return 0;
}//回溯法呼叫自身
void place_queen(int row)
}int main()
這個題目考察遞迴,遞迴屬於很抽象的邏輯,但是在程式演算法中很重要,所以對遞迴的理解運用很重要。 八皇后問題
八皇后問題 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...