跳至正文
View Categories

< 1 min read

主要内容 #

  • 数字金字塔2
  • 求解思路
  • 参考代码

1. 数字金字塔 #

观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。 在上面的样例中,从13到8到26到15到24的路径产生了最大的和86。 输入 第一个行包含R(1≤R≤1000),表示行的数目。 后面每行为这个数字金字塔特定行包含的整数。 所有的被供应的整数是非负的且不大于100。 输出 单独的一行,包含那个可能得到的最大的和。 输入样例
5
13
11 8
12 7  26
6  14 15 8
12 7  13 24 11
输出样例 86

2. 求解思路 #

在上节课中我们采用从上至下的遍历搜索方式,实际上,从下至上的最大值路径与从下至上的最大值路径相同。这一小节将采用从下至上的遍历方式解决问题。 1. 确定dp数组的含义 dp[i][j]定义状态表示从从第n行找一个点作为起点走到aij的路径的最大数字和。 2. 确定递推公式 根据dp[i][j]的定义,可以推导出递推公式为: 当i=n时,dp[i][j]=aij(因为时最下面一行,起点出发能够得到的数字就是本身); 当i<n时,dp[i][j]=max{dp[i+1][j],dp[i+1][j+1]}+aij。
3. dp数组的初始化 从上面的分析可以知道,dp数组全部初始化为0就可以了。 4. 确定遍历顺序 注意这里要按照 i=n→1 的方向推导出所有的状态。 则最终的状态为dp[1][1](因为从小往上推的话,所有路径对应的重点只有一个就是a11)。

3. 参考代码 #

#include<iostream>
using namespace std;
const int maxn = 1010;
int n, a[maxn][maxn], dp[maxn][maxn], ans;
int main()
{
    cin << n;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= i; j ++)
            cin << a[i][j];
    for (int i = n; i >= 1; i --)
    {
        for (int j = 1; j <= i; j ++)
        {
            if (i == n) dp[i][j] = a[i][j];
            else dp[i][j] = max(dp[i+1][j], dp[i+1][j+1]) + a[i][j];
        }
    }
    cout << dp[1][1];
    return 0;
}