1. 程式人生 > >演算法程式設計(JAVA)--迷宮問題

演算法程式設計(JAVA)--迷宮問題

最近遇到了一個經典的演算法問題--迷宮問題,自己試著用JAVA編寫了一下,感覺還比較簡單,直接貼題目和程式碼了。

題目:一個網格迷宮由n行m列的單元格組成,每個大院個要麼是空地(用“.”表示),要麼是障礙物(用"#"表示)。你的任務是找一條從起點到終點的最短移動序列,其中只能上下左右移動到相鄰單元格。任何時候都不能在有障礙物的單元格中,也不能走到迷宮之外。起點為“S”和終點“G”。n,m<100。

主要思路:先找到起點,然後出起點出發,一直走走到死路時,再原路返回,返回到岔路口,選擇另一條路接著走。每到一個岔路口就按固定的順序選擇嘗試,防止重複走。使用一個二維陣列表示迷宮地圖,通過深度搜索來找尋出口,本次編寫並沒有用到堆疊物件,只是用了簡單的遞迴,程式碼後面有詳細的註釋,希望你們能輕鬆看懂

import java.util.Scanner;

public class Main
{
	static int lineX,lineY;//迷宮矩陣的長度和寬度
	static int startX,startY;//起始位置的座標
	static String[][] arr;//迷宮的二維陣列
	static int count=10000;//走的最少步數,初始值設定為10000意為無窮
	public static void main(String[] args){
		Input();//輸入函式
		Running(startX,startY,0);//遞迴函式
		Output();//輸出函式
	}
	public static void Input(){
		Scanner sc = new Scanner(System.in);
		lineX = Integer.parseInt(sc.next());//獲取迷宮長寬
		lineY = Integer.parseInt(sc.next());
		arr = new String[lineX][lineY];//初始化迷宮陣列
		for(int i=0;i<lineX;i++){
			String str = sc.next();
			AddToArr(str,i);//將每一個符號放入二維陣列
		}
	}
	public static void AddToArr(String str,int n){
		for(int i=0;i<lineY-1;i++){
			arr[n][i]=str.substring(i,i+1);
			setStart(str.substring(i,i+1),n,i);//尋找起始位置
		}
		arr[n][lineY-1]=str.substring(lineY-1);
		setStart(str.substring(lineY-1),n,lineY-1);
	}
	public static void setStart(String a,int x,int y){		
		if(a.equals("S")){
			startX=x;
			startY=y;
		}			
	}
	/************遞迴函式************/
	public static void Running(int x,int y,int n){
		//System.out.println(x+" "+y+" "+n);//列印每一步方便理解
		/*判斷上下左右有沒有終點*/
		if(y-1>=0&&arr[x][y-1].equals("G")){
			Running(x,y-1,n+1);
		}
		if(x-1>=0&&arr[x-1][y].equals("G")){
			Running(x-1,y,n+1);
		}
		if(y+1<lineY&&arr[x][y+1].equals("G")){
			Running(x,y+1,n+1);
		}
		if(x+1<lineX&&arr[x+1][y].equals("G")){
			Running(x+1,y,n+1);
		}
		/*如果是終點就將最短路徑記錄一下,然後退出此次函式*/
		if(arr[x][y].equals("G")){
			if(n<count)
				count=n;
			return;
		}
		arr[x][y]="*";//若非終點,將該點做個記號"*"表示已經走過,使以後不再走到這個位置
		/*判斷上下左右有沒有可以走的路*/
		if(y-1>=0&&arr[x][y-1].equals(".")){
			Running(x,y-1,n+1);
		}
		if(x-1>=0&&arr[x-1][y].equals(".")){
			Running(x-1,y,n+1);
		}
		if(y+1<lineY&&arr[x][y+1].equals(".")){
			Running(x,y+1,n+1);
		}
		if(x+1<lineX&&arr[x+1][y].equals(".")){
			Running(x+1,y,n+1);
		}
		//若沒有可以走的路就將此處的記號取消,變回"."
		arr[x][y]=".";
		return;
	}
	public static void Output(){
		if(count==10000){
			System.out.println("沒有出口!");
		}
		else{
			System.out.println("最少需要"+count+"步");
		}
	}
}