[USACO1.5][IOI1994]数字三角形 Number Triangles - 洛谷
视频讲解:数字三角形1_哔哩哔哩_bilibili
解题思路:
1.如果我们把金字塔造型的数字全部左对齐之后,发现形成了一个直角三角形,并且可以利用二维数组来表示,如下图:
2.要求找一段数字值累加最大的序列,输出最大数,从二维数组的第二行开始,每一个数都是自己本身加上正上方或者左上方的数值得来,表示上一行的数向下或者向右下方走一步加上了数值,比如第三行第二列的数字为1,如果从前两行累加过来的时候,其实有两种方法,7-3-1和7-8-1,该选取哪个数呢?题目要求最大值,那么第三行第二列的值应该变为16,表示采用第二种路径累加,那么第四行的数同样是根据前一行的最大值加上本身的值形成的较大值,满足最优子结构,所以可以利用线性DP解决,只不过是二维线性DP,如下图:
3.确定可以使用DP后,现在看三要素,状态,转移,决策,要求最下方的状态是最大值,那么之前的子问题都应该是最大值,每个数都是本身累加正上方或者左上方的较大值而来,状态转移方程为dp[i][j]=max(dp[i][j]+dp[i-1][j],dp[i][j]+dp[i-1][j-1]),决策即选取较大值
4.最后输出最后一行的最大值即可
#include<bits/stdc++.h>
using namespace std;
long long dp[1010][1010];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
cin>>dp[i][j];
}//输入数据到二维数组中
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
dp[i][j]=max(dp[i][j]+dp[i-1][j],dp[i][j]+dp[i-1][j-1]);
}
}
int ans=0;
for(int i=1;i<=n;i++)//找最后一行的最大值
{
if(dp[n][i]>ans)
ans=dp[n][i];
}
cout<<ans;
return 0;
}