1. 程式人生 > >記憶化搜尋路徑_Java實現

記憶化搜尋路徑_Java實現

這是一個簡單的生存遊戲,你控制一個機器人從一個棋盤的起始點(0,0) 走到棋盤的終點(5,5) 。

規則如下:

1. 機器人一開始在棋盤的起始點並有起始點所標有的能量。
2.
 機器人只能向右或者向下走,並且每走一步消耗一單位能量。
3.
 機器人不能在原地停留。

4. 當機器人選擇了一條可行路徑後,當他走到這條路徑的終點時,他將只有終點所標記的能量。

如map圖,機器人一開始在(0,0) 點,並擁有4 單位能量,灰色方塊表示他所能到達的點,如果他在這次路徑選擇中選擇的終點是(1,3)點,當他到達(1,3) 點時將擁有1 單位的能量,並開始下一次路徑選擇,直到到達(5,5) 點。我們的問題是機器人有多少種方式從起點走到終點。


當機器人走到(1,3)時,他只有兩種選擇:1.走(1,4),然後繼續向終點走。2.走(2,3),然後繼續向終點走。那麼也就是說,機器人在(1,3)到終點的走法,就是(1,4)到終點的走法加(2,3)到終點的走法,那麼(1,4)(2,3)到終點的走法有多少種呢?留給遞迴去完成,最終終點臨邊的點到終點只有一步。

當前點到終點的走法=其能到達所有的點到終點的走法的和

通過儲存每一個點到終點的走法,使已計算過的資料能讓後面的計算直接呼叫前面的結果使用,摒棄掉大量的重複計算,這就是記憶化搜尋。

public class 記憶化搜尋 {
	
	static int[][] map={{4,5,6,6,4,3},//初始化地圖
						{2,2,3,1,7,2},
						{1,1,4,6,2,7},
						{5,8,4,3,9,5},
						{7,6,6,2,1,5},
						{3,1,1,3,7,2}};
	
	static int[][] dp={{-1,-1,-1,-1,-1,-1},//初始化記憶表,全初始化為-1,終點初始化為1
						{-1,-1,-1,-1,-1,-1},//表中存放的是當前位置到終點的走法數量
						{-1,-1,-1,-1,-1,-1},
						{-1,-1,-1,-1,-1,-1},
						{-1,-1,-1,-1,-1,-1},
						{-1,-1,-1,-1,-1, 1}};

	public static void main(String[] args) {
		System.out.println(dfs(0,0));//求地圖左上角到右下角終點的走法數量
	}
	
	public static int dfs(int x,int y){
		if(dp[x][y]>=0)//因為地圖被初始化都是-1,所以dp表中大於等於零的點,都說明已經計算過走法了
			return dp[x][y];//直接return,使用之前計算過的結果,避免了大量的重複計算。
		
		dp[x][y]=0;//計算之初,先假定當前點到終點走法為零,便於累和
		
		/*
		 * 下面兩層for迴圈遍歷所有當前點能夠到達的點,當前點到終點的走法數量=其所有子節點到終點的走法的和。
		 * 這是動態規劃思想,當前點到某一個子節點只有一種走法,那麼通過當前子節點為媒介到終點的走法就是子節點到終點的走法。
		 * 那麼當前點到終點的所有走法,就是其所有子節點到終點的走法的和!
		 * 不必揪心於,其子節點到終點的走法,讓遞迴去完成,反正遞迴的盡頭是終點上下左右的點,到終點只有1種走法。
		 * */
		for(int i=0;i<=map[x][y];i++)
			for(int j=0;j<=map[x][y]-i;j++)
				if(x+i>=0 && y+j>=0 && x+i<6 && y+j<6){//判斷地圖越界
					dp[x][y]=dp[x][y]+dfs(x+i,y+j);  //遞迴累和
				}
		
		return dp[x][y];
	}
}