1. 程式人生 > >陣列最短路徑規劃

陣列最短路徑規劃

尋找一條從陣列左上角arr[0][0]到右下角arr[m-1][n-1]的路線,使得沿線經過陣列的數值之和最小。

  1. 遞迴法
    倒著來分析:最後一步到達arr[m-1][n-1]只有兩條路,即通往arr[m-2][n-1]到達或者通往arr[m-1][n-2]到達,最後一步選擇的路線為min{f(m-2,n-1),f(m-1,n-2)},同理可遞迴選擇到arr[m-2][n-1]或arr[m-1][n-2]的路徑。這種遞迴方法效率太低,因為裡面有大量的重複計算過程。

  2. 動態規劃法
    動態規劃其實也是一種空間換取時間的演算法,通過快取計算的中間值,從而減少重複計算的次數。動態規劃採用正向求解,以便利用前面計算的結果。f(i,j)=min{f(i-1,j),f(i,j-1)}+arr[i][j]

    ,從i=1,j=1開始遍歷二維陣列,可以在遍歷的過程中求出所有的f(i,j)的值。同時,把求出的值儲存到另外一個二維陣列cache[i][j]中以供後續使用。

遞迴法

public class HelloWorld{
	public static int getMinPath(int[][] arr,int i,int j) {
		//倒著走到第一個結點,遞迴結果
		if(i==0&&j==0)
			return arr[i][j];
		//選取兩條可能路徑上的最小值
		else if(i>0&&j>0)
			return arr[i][
j]+Math.min(getMinPath(arr,i-1,j),getMinPath(arr,i,j-1)); //下面兩個條件只有一條路可選 else if(i>0&&j==0) return arr[i][j]+getMinPath(arr,i-1,j); else return arr[i][j]+getMinPath(arr,i,j-1); } public static int getMinPath(int[][] arr) { if(arr==null||arr.length==0) return 0; return getMinPath
(arr,arr.length-1,arr[0].length-1); } public static void main(String[] args) { int[][] arr= {{1,4,3},{8,7,5},{2,1,5}}; System.out.println(getMinPath(arr));//結果為17 } }

輸出結果為:

17

動態規劃法

public class HelloWorld{
	public static int getMinPath(int[][] arr) {
		if(arr==null||arr.length==0)
			return 0;
		int row=arr.length;
		int col=arr[0].length;
		//用來儲存計算的中間值
		int[][] cache=new int[row][col];
		cache[0][0]=arr[0][0];
		for(int i=1;i<col;i++) {
			cache[0][i]=cache[0][i-1]+arr[0][i];//初始化上邊cache[0][i]
		}
		for(int j=1;j<row;j++) {
			cache[j][0]=cache[j-1][0]+arr[j][0];//初始化左邊cache[j][0]
		}
		//遍歷二維陣列,取最小的路徑存入剩餘的cache中
		for(int i=1;i<row;i++) {
			for(int j=1;j<col;j++) {
				//可以確定選擇的路線為arr[i][j-1]
				if(cache[i-1][j]>cache[i][j-1]) {
					cache[i][j]=cache[i][j-1]+arr[i][j];
					System.out.println("["+i+","+j+"]");
				}
				else {
					cache[i][j]=cache[i-1][j]+arr[i][j];
					System.out.println("["+(i-1)+","+j+"]");
				}
			}
		}
		System.out.println("["+(row-1)+","+(col-1)+"]");
		return cache[row-1][col-1];
	}
	public static void main(String[] args) {
		int[][] arr= {{1,4,3},{8,7,5},{2,1,5}};
		System.out.println("路徑為:");
		System.out.println("最小值為:"+getMinPath(arr));
	}
}

執行結果為:

路徑為:
[0,1]
[0,2]
[2,1]
[2,2]
[2,2]
最小值為:17