AcWing 898. 数字三角形
题目
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输入格式
第一行包含整数 \(n\),表示数字三角形的层数。
接下来 \(n\) 行,每行包含若干整数,其中第 \(i\) 行表示数字三角形第 \(i\) 层包含的整数。
输出格式
输出一个整数,表示最大的路径数字和。
数据范围
\(1 \le n \le 500\),
\(-10000 \le 三角形中的整数 \le 10000\)
输入样例:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例:
30
题解
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 510;
int n;
int f[N][N], w[N][N]; //f[i][j]存从三角形底部到每一个点(i,j)的路径最大值 w[i][j]存三角形内每个节点自身的值
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= i; j ++ ) //当前层的元素个数就是层数
scanf("%d", &w[i][j]);
for (int j = 1; j <= n; j ++ ) f[n][j] = w[n][j]; //三角形最后一层的路径最大值就是其自身的值
for (int i = n - 1; i > 0; i -- ) //从倒数第二层向上遍历求每个节点路径最大值 因为最后一层节点最大值已经求得
for (int j = 1; j <= i; j ++ )
f[i][j] = max(f[i + 1][j] + w[i][j], f[i + 1][j + 1] + w[i][j]); //当前节点的最大值 从他两个子节点的最大值加上它自身的值取max得到的
printf("%d\n", f[1][1]); //三角形路径最大值在顶点取得
return 0;
}
------ 接下来我们优化代码
//可以观察到上面代码w[i][j]是可以直接被f[i][j]取代的
//先将每一个节点最大值f[][]赋值为其自身的价值,
//这样我们不用专门利用循环将最后一层w[n][j]赋值给f[n][j],这行代码可以直接删去
//f[i][j] = max(f[i + 1][j] + w[i][j], f[i + 1][j + 1] + w[i][j])
//这行代码也可以改写成f[i][j] = max(f[i + 1][j], f[i + 1][j + 1]) + f[i][j]
//因为此时f[i][j]还未被改变,还是初始录入的节点自身价值,可以直接加
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 510;
int n;
int f[N][N];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= i; j ++ )
scanf("%d", &f[i][j]);
for (int i = n - 1; i > 0; i -- )
for (int j = 1; j <= i; j ++ )
f[i][j] += max(f[i + 1][j], f[i + 1][j + 1]); //直接写成+=
printf("%d\n", f[1][1]);
return 0;
}