数字三角形问题
问题描述
给定一个由n行数字组成的数字三角形,如图所示。计算出从三角形的顶至底的一条路径,使该路径经过的数字总和最大。
输入的第一行是数字三角形的行数n, 1 <= n <= 100。接下来n行是数字三角形各行中的数字。所有数字在0~99之间。
示例
input:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
output:
30
分析
(1)自顶向下
如下图所示,我们可以先初始化,数字三角形的两条斜边(红色部分,因为斜边的上的点只能够与它上面的一个点相连),然后计算三角形内部所有的值(蓝色部分,取该点上一层的左肩上的值与右肩上的值的较大值,在加上自身的值,得到该点的值),最后在三角形的底边找出一个最大值,即为结果。
(2)自底向上
逆向思维,因为上层点的值只由该点下一层左右两个点的值决定,最终结果在a[1][1]。
a[i][j] += max(a[i + 1][j], a[i + 1][j + 1]);
(1)自顶向下
#include <stdio.h>
#include <algorithm>
using namespace std;
int a[105][105];
int
main() {
int n, i, j, amax;
scanf("%d", &n);
for( i = 1; i <= n; i++ ) {
for( j = 1; j <= i; j++ ) {
scanf("%d", &a[i][j]);
}
}
for( i = 2; i <= n; i++ ) {
a[i][1] += a[i - 1][1];
a[i][i] += a[i - 1][i - 1];
}
for( i = 3; i <= n; i++ ) {
for( j = 2; j < i; j++ ) { // j < i,注意一下边界
a[i][j] += max(a[i - 1][j - 1], a[i - 1][j]);
}
}
amax = a[n][1];
for( j = 2; j <= n; j++ ) {
if( a[n][j] > amax ) {
amax = a[n][j];
}
}
printf("%d\n", amax);
return 0;
}
(2)自底向上
#include <stdio.h>
#include <algorithm>
using namespace std;
int a[105][105];
int
main() {
int n, i, j;
scanf("%d", &n);
for( i = 1; i <= n; i++ ) {
for( j = 1; j <= i; j++ ) {
scanf("%d", &a[i][j]);
}
}
for( i = n - 1; i >= 1; i-- ) {
for( j = 1; j <= i; j++ ) {
a[i][j] += max(a[i + 1][j], a[i + 1][j + 1]);
}
}
printf("%d\n", a[1][1]);
return 0;
}