趣味集算:八皇后問題

有關國際象棋的問題不少,八皇后問題就是其中至關著名的一個。在 8×8 的國際象棋棋盤中,放入 8 個皇后,使它們不互相攻擊,共有多少種方法呢?函數

8Q1png

8q2png

國際象棋中皇后的威力巨大,攻擊範圍是同一行、同一列以及同一斜行,所以,符合條件的 8 個皇后必須都不在同一行、同一列或者同一斜行上。spa

因爲每一行中只能放入一個皇后,因此可使用一個長度爲 8 的序列,依次設入每行中皇后所在的列數,以此來表示皇后的放置狀態。當某一行尚未置入皇后時,即該行沒有一列上有皇后,記爲 0;而每次置入新的皇后時,若是列數不是序列中已有的,就說明沒有皇后在同一列中。這樣,不一樣行、不一樣列就能很容易的斷定了。3d

那麼,在置入新的皇后時,就只須要保證它與已有的皇后都不在同一斜行上了。若是一個皇后在 m 行 k 列,那麼在 m+n 行,最多隻有兩個位置和它在同一斜行上,並且這兩個位置距離它的橫向距離等於縱向距離,也就是說最多blog

只有 (m+n,k+n) 和 (m+n,k-n) 這兩個位置與這個皇后在同一斜行上。遞歸

這樣,只要把每一個皇后在每一行的全部狀況都檢查一遍,就能夠知道共有多少種狀況知足要求了。圖片


通過上面的抽象分析,咱們只須要在集算器中,經過循環計算來完成這些判斷就好了。具體代碼以下:
圖片描述it

第 1 行,A1 就是記錄皇后放置狀態的序列;B1 定義了一個變量 i,用來在計算時記錄當前放置皇后的行。class

第 2 行代碼,每循環一次,就把當前行的皇后下移 1 列,用這樣的方法遍歷行中每一個位置。變量

第 3 行代碼,若是棋子移到了第 9 列,說明當前行的棋子已經完成了全部位置的循環,此時,應該把當前行的記錄復原爲 0,並將 i 減 1,能夠返回去繼續上一行的遍歷;特別的,當第 1 行也所有循環後,說明完成了遍歷,此時 i 被設爲 0,中止循環。循環

第 4 行代碼,在移動第 1 行皇后時,能夠不用判斷,直接開始放置第 2 個皇后。

第 6 行代碼,判斷已放好的皇后中,是否存在同一列的;

第 7 行代碼,判斷已放好的皇后中,是否存在同一斜行的。若是既沒有同一列的,也沒有同一斜行的,就能夠繼續放置下一行的皇后了。

若是此時 8 個皇后都放置成功,則在第 9 行代碼中記錄下當前每一個皇后的位置。

通過計算,A10 中結果以下:
8q3png

能夠在 C1 中查看具體結果:
8q4png


固然,還能夠用經典的遞歸方式解決這個問題,集算器中遞歸調用子函數的方法的代碼以下:

圖片描述
在 A2 定義的子程序中,在一個新行中嘗試放置皇后,在 B2 中循環每個可能的列。

A5 中的子程序用來判斷新的一行是否可使用指定的列,其中在 C5 中查看是否本列已存在皇后,第 6 行查看是否已有皇后在同一斜行,在這樣的狀況下說明不能放置。若是某一列能夠放置,則判斷是否 8 個皇后都放置成功,若是已所有設置成功則記錄在 C1 中。若是未放置滿,則遞歸調用 A2 中的子程序,繼續在下一行放置。這種方法的代碼更易理解,計算結果與前面的方法是相同的。

相關文章
相關標籤/搜索