首先,緬懷數學王子——高斯,在沒有計算機且圖論相對不完善的時代,手動得出八皇后的76種解法。
學習了遞迴有兩年多,沒用遞迴做解決過八皇后的問題。今天,經過一番內心的掙扎,終於寫出了這個問題的解法。
問題:在8×8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列且同一斜線上,問有多少種擺法。
分析問題:個人理解,看到問題,第一反應是畫圖,但是8*8的圖有點大。於是簡化問題,做2*2的圖。
當將的第乙個皇后(黑色代表皇后)放入棋盤,我就知道,此山不能容二虎。於是我們從3*3開始。
嗯,不出意外,3*3的圖最多放兩個。
4*4這裡就不放圖了,還是不行,只能放3個滿足條件的皇后。
but當棋盤變為5*5時,就可以實現5個皇后不會攻擊到彼此。
例圖:(只是其中一種情況)
現在,我們回頭再看問題。這個問題,有點像數獨。嗯,數獨中有乙個規則是:同乙個數字,一行一列只能出現一次。而八皇后問題也有條件:每個皇后所處的行列不能有其他的皇后。而這個八皇后多了乙個條件:這個皇后所處的斜線上也不能幽皇后。這裡提供乙個思路:將數獨中的數字可以完美轉換成乙個n*n矩陣的,而矩陣在進行列變化時,其行列的總和不變,也就是說,這個數獨的本質沒變,他還是數獨,不會出現同一行或者同一類有相同的數字。將這一思想引入八皇后問題,我們是否可以先初始化乙個滿足乙個不處於同一行、同一列的八皇后?這個條件很容易滿足,如下圖:
當所有皇后出現在對角時,就初始了皇后的位置,且滿足所有不處於同一行、同一列。接下來我們只用進行列邊換,以完成多個皇后出現在同一斜線上的問題。
接下來,當我們進行行類變換時就會發現,當行邊換與列邊換變換可以達到同樣的效果:
當我們將初始情況進行x1x2變化時與y1y2效果一樣。那麼,我們就可以只進行一種邊換來解決這個問題。
這樣做,直接將二維問題轉化為一維。
現在,我們將每個皇后打標記,標記的號碼為他的初始行數(這裡行數與列數相等)。則會出現(以為例五皇):12345。現在我們要解決的問題是,如何邊換12345的順序,使他再轉化到棋盤中時,同一斜線沒有多個皇后。
我們現分析,出現同一斜線的必要條件:回到二維棋盤,當且僅當兩個棋子的形成的直線斜率為1或者-1時,在同一斜線時。也就是:x2-x1=y1-y2或者y2-y1。好了,分析到這,問題基本思路就解決了。
還有乙個要說的是,這一串數字的(x,y)屬性體現在**?
答:數字所處數字串的位置為y值,該處所對應的值為x值。(x,y是等價的,是可以互換的,但邊換的過程中不能互換)
個人思路,無優化,僅供參考。
我們可以用遍歷樹解決來解決這一問題:
求解的過程類似於樹的遍歷,有多分枝的出口(遞迴中遞的過程),每次在向下遞的同時判斷,這個操作是否可行。
而返回的路徑只有一條就是上一層(遞迴中遞的過程),及就是乙個樹節點可以有多個孩子,他的父節點只有乙個。
這是遞迴的思想,再向其中加入判斷,就可以完成不在同一斜線的可能。
**如下:
package 實驗;
public class eight_queens
private static void e_q(int arr,int n)
else if(n==num)
} else
}} }
private static boolean isyx(int arr,int n,int i)
return true;
} private static boolean isnoin(int arr,int n,int i)
}
八皇后問題的遞迴解法與回溯優化
關於八皇后問題有很多種解法,今天只寫一種利用全排列的解法,其他的一些解法看情況在整理補充。全排列演算法 在8 8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。對於這個問題如果採用組合數的的方式來列舉每一種情況,那麼將需要 但換個思路,...
八皇后問題 遞迴求解法
include include include 八皇后問題遞迴方法實現 using namespace std ofstream file 用以計數計算結果的數目 int count 1 列印的棋盤其中列印1的位置是皇后的位置,0空位。這裡因為在控制台看不到全部,所有做了在檔案中輸出所有的解 int...
八皇后及任意多皇后問題解法之遞迴解法
遞迴解法的基本原理是把乙個大問題拆分成幾個類似的小問題,小問題繼續拆解成更小的問題,直到不能拆解的單元問題為止,再把所有單元問題的解匯集成問題的全部解。就八皇后問題而言,可以先擺第一列,共八種位置選中,每種位置選擇下,剩餘的八行七列中繼續擺放其他皇后,即變成了八個 八行七列棋盤擺七個皇后問題 的解的...