動態規劃——數字三角形最大和
阿新 • • 發佈:2019-02-15
題目描述:
求數字三角形從頂層到底層的最大和,路徑抉擇時只能向下或向右下走。
本題中的數字三角形:
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);
}