给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输入格式
第一行包含整数n,表示数字三角形的层数。
接下来n行,每行包含若干整数,其中第 i 行表示数字三角形第 i 层包含的整数。
输出格式
输出一个整数,表示最大的路径数字和。
数据范围
1 ≤ n ≤ 500,
−10000 ≤ 三角形中的整数 ≤ 10000
输入样例:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例:
30
题目大意:
给出一个数字三角形,从上往下,每一个节点都可以移动至距离最近的左下或右下节点,你需要选择一条路,使得路径上的数字之和最大。
解题思路:
dp经典问题之数字三角形模型,处理动态规划问题从两方面入手,状态表示和状态计算。
- 状态表示:用二维去表示状态,f (i, j) 表示的集合是起点走到i,j点的所有走法的路径和,而属性是最大值,总结一下,f (i, j) 表示从起点走到i, j 时的路径和的最大值。
- 状态计算: 集合的划分,这要看f (i, j) 可以从哪些集合转移过来,结合题意,则该点可以从左上走下来,也可以从右上走下来,所以二者取最大值即可得到状态转移方程:f[i][j] = max(f[i - 1][j], f[i][j - 1]) + f[i][j]
Code:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 510;
int f[N][N];
int n;
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= i; j ++)
cin >> f[i][j];
for (int i = 2; i <= n; i ++)
for (int j = 1; j <= i; j ++)
if (j == 1) f[i][j] = f[i - 1][j] + f[i][j];//特判一下,因为等于1和n的时候只能从一种集合转移过来
else if (j == i) f[i][j] = f[i - 1][j - 1] + f[i][j];
else f[i][j] = max(f[i - 1][j], f[i - 1][j - 1]) + f[i][j];
int res = 0;
for (int i = 1; i <= n; i ++) res = max(res, f[n][i]);
cout << res << endl;
return 0;
}