求迷宮最短路徑【佇列+回溯】
阿新 • • 發佈:2018-10-31
求迷宮的最短路徑(0表示通路,1表示受阻)
問題:有一個迷宮,求從入口到出口的最短路徑,其中0表示通路,1表示受阻,規定向下是X軸,向右是Y軸
輸入:第一個數迷宮x軸的長度,第二個數迷宮y軸的長度,緊接著入口點的座標和出口的座標,之後是一個迷宮
輸出:迷宮所走的路徑的座標
樣例:
INPUT:
6 8
1 1
6 8
0 1 1 1 0 1 1 1
1 0 1 0 1 0 1 0
0 1 0 0 1 1 1 1
0 1 1 1 0 0 1 1
1 0 0 1 1 0 0 0
0 1 1 0 0 1 1 0
OUT:
(1,1)-->(2,2)-->(3,3)-->(3,4)-->(4,5)-->(4,6)-->(5,7)-->(6,8)
基本思想:從迷宮入口(1,1)出發,向四周搜尋,記下所有一次能通達的座標p11,p12,…p1k,然後從p11,p12,…p1k出發,向四周搜尋,標記搜尋過的點……直至達到出口點(m,n),然後從出口點沿搜尋路徑回溯直至入口。
注意點:
1.為什麼從(1,1)點出發而不從(0,0)點出發?
若從(0,0)點出發向四周八個點進行搜尋是搜尋不了的,其實就是為了程式碼的統一
2.為什麼使用佇列這種資料結構?為什麼使用佇列記錄的路徑是最短的呢?
1.仔細分析一下這個迷宮,我們從(1,1)點出發,到下一個點(2,2),在(2,2)這裡有兩種情況都應該記錄下來,以此類推把之後的搜尋到的記錄都記錄到最後,先搜尋到的應該先進行繼續搜尋,這種邏輯結構符合佇列的邏輯結構
2.對角線最短這應該大家都懂,假設有一個迷宮是這樣的
序號為1的地方表示入口而序號為9的地方表示出口,顯而易見這個迷宮其實全是通路的,從起點都能到達終點
從序號1向四周搜尋,搜到的應該是序號2,4,5把這三個點儲存到佇列中,從序號2開始搜尋到序號3儲存到佇列中,序號4也是一樣,把7,8兩個點加入到佇列中,但是從5開始搜尋的時候儲存的是6,9兩個點,最先找到終點的一定是5.因為2或者4還要很多步數一定是比序號5慢的
下面是程式碼:
package 佇列的應用_搜迷宮最短路徑; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class FindMinLoad { public static void main(String[] args) { Scanner in = new Scanner(System.in); int x = in.nextInt();//X軸長度 int y = in.nextInt();//Y軸 int[][] mg = new int[x+2][y+2];//迷宮 int Xrk = in.nextInt();//入口 int Yrk = in.nextInt(); int Xck = in.nextInt();//出口 int Yck = in.nextInt(); for (int i = 0; i < mg[0].length; i++) { mg[0][i] = 1; mg[x+1][i] = 1; } for (int i = 0; i < mg.length; i++) { mg[i][0] = 1; mg[i][y+1] = 1; } for (int i = 1; i < mg.length-1; i++) { for (int j = 1; j < mg[i].length-1; j++) { mg[i][j] = in.nextInt(); } } // for (int i = 0; i < mg.length; i++) { // for (int j = 0; j < mg[i].length; j++) { // System.out.print(mg[i][j]+" "); // } // System.out.println(); // } //if(x==1 && y==1) { //System.out.println("0"); //}else { int[][] queue = new int[x*y][3]; queue[0][0] = Xrk; queue[0][1] = Yrk; queue[0][2] = -1; int front = 0; int rear = 1; OUT: while(front!=rear) { mg[queue[front][0]][queue[front][1]] = 1; for (int i = queue[front][0]-1; i <= queue[front][0]+1; i++) { for (int j = queue[front][1]-1; j <= queue[front][1]+1; j++) { if(mg[i][j]==0) {//通路記錄下 queue[rear][0] = i; queue[rear][1] = j; queue[rear++][2] = front; mg[i][j]=1; if(i==Xck && j==Yck) { break OUT; } } } } //System.out.println((queue[rear-1][0]!=Yck)+" "+(queue[rear-1][1]!=Xck)); front++; } List<String> list = new ArrayList<String>(); for (int i = rear-1; i>=0; i--) { //System.out.println("("+queue[i][0]+","+queue[i][1]+")"); list.add("("+queue[i][0]+","+queue[i][1]+")"); i = queue[i][2]+1; } for (int i = list.size()-1; i>0; i--) { System.out.print(list.get(i)+"-->"); } System.out.print(list.get(0)); //} } }