洛谷说今天适合写题解,所以继续每周一水(doge),而这次难度再次加大,我们来讲动态规划。
这道题呢也比较简单,属于动态规划的模板题了(怎么感觉我只讲模板题),类型是数塔。
题目描述:
观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。
在上面的样例中,从13到8到26到15到24的路径产生了最大的和86。
输入:
第一个行包含𝑅(1≤𝑅≤1000),表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
所有的被供应的整数是非负的且不大于100。
输出:
单独的一行,包含那个可能得到的最大的和。
输入样例:
5
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11
输出样例:
86
题目分析:
R指行数,接着的R行输入1,2,3...,R个数,表示点的数字。
我们可以从最后一行开始向上遍历,也可以从最上面一行往下遍历。为了方便理解,我们选择从下往上的思路。
动态规划,最重要的是状态转移方程(也就是靠个人的数学找规律能力)。在本题中,我们要求一个点最大值,可以选择这个数下面的数(i-1,j)以及下面的右边的数(i-1,j-1),既然是最大值,那么就用这个点的数加上这个数下面的数以及下面的左边的数的最大值。由此,我们就得出了状态转移方程:
dp[i][j]=dp[i][j]+max(dp[i+1][j],dp[i+1][j+1])
代码:
说实话,动态规划除了状态转移方程比较难之外都挺简单的。(不会有人不会输入来看动态规划题解吧doge)。所以我直接附上AC代码供大家食用。
#include<bits/stdc++.h>
using namespace std;
long long dp[1145][1145],n;//定义dp数组村存储每个点的原数
int main()
{
//输入
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
cin>>dp[i][j];
//对dp数组进行操作
for(int i=n-1;i>=1;i--)
for(int j=1;j<=i;j++)
dp[i][j]+=max(dp[i+1][j],dp[i+1][j+1]);//状态转移方程的使用
cout<<dp[1][1];//输出最上面的(最大值)
}