一、簡介
回溯法的基本思想是:對一個包括有很多結點,每個結點有若干個搜索分支的問題,把原問題分解為對若干個子問題求解的算法。當搜索到某個結點、發現無法再繼續搜索下去時,就讓搜索過程回溯(即退回)到該結點的前一結點,繼續搜索這個結點的其他尚未搜索過的分支;如果發現這個結點也無法再繼續搜索下去時,就讓搜索過程回溯到這個結點的前一結點繼續這樣的搜索過程;這樣的搜索過程一直進行到搜索到問題的解或搜索完了全部可搜索分支沒有解存在為止。
該方法可以使用堆棧實現。也可以使用遞歸實現,遞歸實現的話代碼比較簡單,較難理解建議自己打斷點一步步跟蹤理解
//=============
1 /** 2 * 回溯法解決,迷宮算法 3 * 4 * @author MIX 5 * 6 */ 7 public class MyMaze { 8 9 private static int startPosI; // 入口的i下標 10 private static int startPosJ; // 入口的j下標 11 private static int endPosI; // 出口的j下標 12 private static int endPosJ; // 出口的j下標 13 14 // 設置迷宮入口的坐標 15 public void setStart(int startPosI, int startPosJ) { 16 17 MyMaze.startPosI = startPosI; 18 MyMaze.startPosJ = startPosJ; 19 } 20 21 // 設置迷宮出口的坐標 22 public void setEnd(int endPosI, int endPosJ) { 23 24 MyMaze.endPosI = endPosI; 25 MyMaze.endPosJ = endPosJ; 26 } 27 28 // 迷宮搜索通路的算法 29 /** 30 * 31 * @param cell 32 * 迷宮地圖 33 * @param i 34 * 入口的i坐標 35 * @param j 36 * 入口的j坐標 37 */ 38 public static void visited(int[][] cell, int i, int j) { 39 // 表示此路為通 40 /* 41 * 該標記記為走過該路徑,一旦該路徑為通路且走到了該路徑那么就將該位置置為1 42 */ 43 cell[i][j] = 1; 44 String oriention = null; 45 if (i == endPosI && j == endPosJ) { // 找到了出口 46 System.out.println("找到一條通路"); 47 for (int m = 0; m < cell.length; m++) { 48 for (int n = 0; n < cell[i].length; n++) { 49 if (cell[m][n] == 2) { 50 System.out.print("2"); 51 } else if (cell[m][n] == 1) { 52 System.out.print("*"); 53 } else { 54 System.out.print(" "); 55 } 56 } 57 System.out.println(); 58 } 59 } 60 61 // 向左邊尋找通路 62 if (cell[i][j - 1] == 0) { 63 oriention = "left"; 64 visited(cell, i, j - 1); 65 } 66 // 向右尋找通路 67 if (cell[i][j + 1] == 0) { 68 oriention = "right"; 69 visited(cell, i, j + 1); 70 } 71 // 向上尋找通路 72 if (cell[i - 1][j] == 0) { 73 oriention = "up"; 74 visited(cell, i - 1, j); 75 } 76 // 向下尋找通路 77 if (cell[i + 1][j] == 0) { 78 oriention = "down"; 79 visited(cell, i + 1, j); 80 } 81 /* 82 * 一旦該路徑走到了死胡同里,清理走過的路徑將當前位置重新標志為1,推出當前遞歸的迭代堆棧,返回上一次,繼續 83 * 在當前函數里面的應用主要是清理之前走過的但是被標記為1的位置,將該位置重新置為0,以便下一次的位置可以訪問 84 */ 85 oriention = "無知的我"; 86 cell[i][j] = 0; 87 88 } 89 90 public static void main(String[] args) { 91 // 初始化一個迷宮地圖 92 int[][] maze = { { 2, 2, 2, 2, 2, 2, 2, 2, 2 }, 93 { 2, 0, 0, 0, 0, 0, 0, 0, 2 }, { 2, 0, 2, 2, 0, 2, 2, 0, 2 }, 94 { 2, 0, 2, 0, 0, 2, 0, 0, 2 }, { 2, 0, 2, 0, 2, 0, 2, 0, 2 }, 95 { 2, 0, 0, 0, 0, 0, 2, 0, 2 }, { 2, 2, 0, 2, 2, 0, 2, 2, 2 }, 96 { 2, 0, 0, 0, 0, 0, 0, 0, 2 }, { 2, 2, 2, 2, 2, 2, 2, 2, 2 } }; 97 98 // MyMaze cell = new MyMaze(); 99 // cell.setStart(1, 1); 100 // cell.setEnd(7, 7); 101 // cell.visited(maze, startPosI, startPosI); 102 int[][] maze2 = { { 2, 2, 2, 2 }, { 2, 0, 0, 2 }, { 2, 0, 0, 2 }, 103 { 2, 2, 2, 2 } }; 104 MyMaze cell = new MyMaze(); 105 cell.setStart(1, 1); 106 cell.setEnd(2, 2); 107 cell.visited(maze2, startPosI, startPosJ); 108 } 109 110 }
//上面代碼里面的測試代碼我是用了一個比較簡單的4*4矩陣進行測試,方便斷點觀察,理解該算法的思路。
//這里其實和遞歸方法的方法棧應用有點類似。