问题描述:
有一个形式如下的数字三角形:
7
3 8
8 1 0
2 7 7 4
4 5 2 6 5
从三角形顶点,沿左斜线方向或右斜线方向下降到三角形底边的路线是一条合法路径。
例如,图中用红色标出的路径就是合法的;我们可以将这条路径记为“LLRL”,它经过了7,3,8,7,5这5个数字,它们的和是30。
请编写一个程序,求解一条合法路径,使这条路径上经过的各数字的总和最大,并把这个最大的总和以及你的路径输出出来。如果路径不止一条,则优先选择向左走。
分析:
问题可以看成如下:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
编写一个程序计算从顶至底的某处的一条路径,使该路径所经过的数字的总和最大。每一步可沿直线向下或右斜线向下走。
(由上至下编号)
1、最优子结构:从下往上看,最底层到底 n-1 层的最优解包含最底层到底 n 层的最优解。
2、重叠子问题:要求得从最底层到 n 层的解需求的从最低层到 n-1 层的解
3、由以上两个性质,本题最适合用动态规划解
4、状态转移方程:
res[i-1][j] = max{(array[i-1][j] + res[i][j]),(array[i-1][j] + res[i][j+1]}
说明:res:结果数组。表示第i层第j个数字到最低端的最优解。
程序代码如下:(c++)
#include <iostream>
using namespace std;
int array[5][5]={{7},{3, 8}, {8, 1, 0}, {2, 7, 4, 4}, {4, 5, 2, 6, 5}};
int res[5][5];
int max(int a, int b){
return ((a>b)?a:b);
}
int digit_triangle(int (*array)[5], int n){
int i, j;
for (j = 0; j < n; j ++){
res[n-1][j]=array[n-1][j];
}
for (i = 4; i >= 0; --i){
for (j = 0; j < i; ++j){
res[i-1][j] = max(res[i][j]+array[i-1][j], res[i][j+1]+array[i- 1][j]);
}
}
return res[0][0];
}
int main(){
int result;
result = digit_triangle(array, 5);
cout <<result << endl;
return 0;
}