1. 程式人生 > >動態規劃——數字三角形最大和

動態規劃——數字三角形最大和

題目描述:

求數字三角形從頂層到底層的最大和,路徑抉擇時只能向下或向右下走。

本題中的數字三角形:

7

3,8

8,1,0

2,7,4,4

4,5,2,6,5

題解:若三角形為等腰三角形或其他形式,先化為上述矩陣的樣子方便解答,可用矩陣int [][]matrix={{7},{3,8},{8,1,0},{2,7,4,4},{4,5,2,6,5}}表示。

//***純遞迴,找到遞迴公式便找到了DP_狀態轉移方程;
	public int triangleSum(int[][] matrix,int m,int n)
	{
		if(m>=matrix.length||n>m)
			return 0;
		
		return  triangleSum(matrix,m+1, n)>triangleSum(matrix,m+1, n+1)?\
                        triangleSum(matrix,m+1, n)+matrix[m][n]:triangleSum(matrix,m+1, n+1)+matrix[m][n];
	}


//***自頂向下記憶化方式
	public  int [][]data=new int[5][5];//這裡的matrix為[5][];
	public int triangleSum1(int[][] matrix,int m,int n)
	{
        if(m==matrix.length-1&&n<=m)
        {
        	data[m][n]=matrix[m][n];
        	return data[m][n];
        }
	  //將遞迴中沒有被記錄的值記錄;
		if(data[m+1][n]==0)
			data[m+1][n]=triangleSum1(matrix,m+1,n);
		if(data[m+1][n+1]==0)
			data[m+1][n+1]=triangleSum1(matrix,m+1,n+1);
      //直接用記錄中的值得到本次需要返回的值;
		data[m][n] = data[m+1][n]>data[m+1][n+1]?data[m+1][n]+matrix[m][n]:data[m+1][n+1]+matrix[m][n];
		return data[m][n];
}


//***DP_自底向上遞推
	public int [][]path=new int [5][5];//二維陣列path用來存放決策的狀態;
	public int triangleSum_DP(int[][] matrix,int m,int n)
	{
		int [][]data=new int[5][5];
		for(int i=0;i<5;i++)//遞推公式中的邊界條件需要額外在矩陣中賦值;
			data[4][i]=matrix[4][i];
		//開始自底向上逐級遞推,data為最大和路徑矩陣;
		for(int i=4;i>m;i--)
		{
			for(int j=0;j<=i-1;j++)
			{
				if(data[i][j]>data[i][j+1])
				{
					data[i-1][j]=data[i][j]+matrix[i-1][j];
					path[i-1][j]=1;
				}
				else
				{
					data[i-1][j]=data[i][j+1]+matrix[i-1][j];
					path[i-1][j]=2;
				}
			}
		}
		return data[m][n];
	}

//***恢復路徑;列印結果為 73875;
//path[5][5] ==[[1, 0, 0, 0, 0], [1, 1, 0, 0, 0], [2, 1, 2, 0, 0], [2, 1, 2, 1, 0], [0, 0, 0, 0, 0]]
	public void pathback(int[][]matrix,int[][]path,int i,int j)
	{
//path[5][5]中第5行的值全部為預設的0,而遞迴條件是值為1或2則遞迴,所以陣列沒有越界。
		System.out.print(""+matrix[i][j]);
		
		if(path[i][j]==1)
			pathback(matrix,path,i+1, j);
		if(path[i][j]==2)
			pathback(matrix,path,i+1, j+1);
	}