题目描述:
求数字三角形从顶层到底层的最大和,路径抉择时只能向下或向右下走。
本题中的数字三角形:
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);
}