主要内容 #
- 数字金字塔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; }