Java算法——回溯法


回溯法
一種選優搜索法,又稱試探法。利用試探性的方法,在包含問題所有解的解空間樹中,將可能的結果搜索一遍,從而獲得滿足條件的解。搜索過程采用深度遍歷策略,並隨時判定結點是否滿足條件要求,滿足要求就繼續向下搜索,若不滿足要求則回溯到上一層,這種解決問題的方法稱為回溯法。

回溯法解求解問題步驟

  1. 針對給定問題,定義問題的解空間樹;
  2. 確定易於搜索的解空間結構;
  3. 以深度優先方式搜索解空間,並且在搜索過程中用剪枝函數避免無效搜索;
  4. 用回溯法求解問題,重點是設計問題的解空間樹,其解題過程則是深度遍歷解空間樹的過程。

解空間樹
是依據待求解問題的特性,用樹結構表示問題的解結構、用葉子表示問題所有可能的解的一棵樹。

解空間樹的形成過程
我們可以把求解問題的過程當作一系列的決定來考慮,回溯法對每一個決定都系統地分析所有可能的結果。而每一次決定即為解空間樹中的一個分支結點,各種可能的結果便形成了各棵不同的子樹,問題最終所有可能的解將展現在所有的葉子上。這便是解空間樹的形成過程。

對解空間樹的遍歷可搜索到問題所有可能的解,因此,可獲得滿足要求的全部解,也可通過對所有解的比較選擇獲得最優解。

由於空間問題,下面給出一個三皇后問題的解空間樹(3皇后問題無解),樹中第i層的結點決定第i行皇后的擺放位置,均有三種不同的選擇,便形成了三個孩子結點,但其中不包括不符合要求的布局。N皇后問題解空間樹與三皇后問題解空間樹類似。

 

求解N皇后問題的回溯法
N皇后問題要求求解在N*N的棋盤上放置N個皇后,並使各皇后彼此不受攻擊的所有可能的棋盤布局。皇后彼此不受攻擊的約束條件是:任何兩個皇后均不能在棋盤上同一行、同一列或者同一對角線上出現。

由於N皇后問題不允許兩個皇后在同一行,所以,可用一維數組X表示N皇后問題的解,X[i]表示第i行的皇后所在的列號。例如一個滿足要求的四皇后棋盤布局如下圖所示,其結果X數組的值為:[2, 4, 1, 3]。

 

由上述X數組求解N皇后問題,保障了任意兩個皇后不在同一行上,而判定皇后彼此不受攻擊的其他條件,可以描述如下:
(1)X[i] = X[s],則第i行與第s行皇后在同一列上。
(2)如果第i行的皇后在第j列,第s行皇后在第t列,即X[i] = j和X[s] = t,則只要i-j = s-t或者i+j = s+t,說明兩個皇后在同一對角線上。

對兩個等式進行變換后,得到結論:只要|i-s| = |j-t|(即i-s = X[i]-X[s]),則皇后在同一對角線上。

解N皇后問題需要遍歷解空間樹,遍歷中要隨時判定當前結點棋盤布局是否符合要求,符合要求則繼續向下遍歷,直至判斷得到一個滿足約束條件的葉子結點,從而獲得一個滿足要求的棋盤布局;不符合要求的結點將被舍棄(稱之為剪枝),並回溯到上一層的結點繼續遍歷。當整棵樹遍歷結束時,已獲得所有滿足要求的棋盤布局。

八皇后問題java實現:

public class Queen {
public static int num = 0; // 方案數
public static final int MAXQUEEN = 8; // 皇后數
public static int[] cols = new int[MAXQUEEN]; // 定義數組,表示MAXQUEEN列棋子中皇后擺放位置
/*
* @param n:填第n列的皇后
*/

public void getCount(int n) {
boolean[] rows = new boolean[MAXQUEEN];
for (int m = 0; m < n; m++) {
rows[cols[m]] = true;
int d = n - m;
// 正斜方向
if (cols[m] - d >= 0) {
rows[cols[m] - d] = true;
}
// 反斜方向
if (cols[m] + d <= (MAXQUEEN - 1)) {
rows[cols[m] + d] = true;
}
}
for (int i = 0; i < MAXQUEEN; i++) {
if (rows[i]) {
// 不能放
continue;
}
cols[n] = i;
// 下面仍然有合法位置
if (n < MAXQUEEN - 1) {
getCount(n + 1);
} else {
// 找到完整的一套方案
num++;
printQueen();
}
}
}

private void printQueen() {
System.out.println("第" + num + "種方案");
for (int i = 0; i < MAXQUEEN; i++) {
for (int j = 0; j < MAXQUEEN; j++) {
if (i == cols[j]) {
System.out.print("0 ");
} else {
System.out.print("+ ");
}
}
System.out.println();
}
}

public static void main(String[] args) {
Queen queen = new Queen();
queen.getCount(0);
}
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM