看到这道题,脑海中想到的就是dp,第一步就可以开始找规律,但这时候发现一个有意思的地方,题目里说:“路径上的每一步只可沿左斜线向下或右斜线向下走”,然而看到输入样例的时候
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
会发现实际上其实是:“只能向下走或者向右下走”。
此时我们可以定义一个二维数组:路径和sum[行][列],到这一行列的方法有两种,一种是从正上方sum[行-1][列],一种是从左上方sum[行-1][列-1],可以发现,到第一行第一列的时候,没有上方和左上方,所以可以初始化:
sum[0][0]=n[0][0];//n是存放题目提供的数字三角形的数组
而且还可以发现,第一列只能从上方来,每行最后一列的只能从左上方来,所以需要特殊对待:
for(int i=1;i<N;i++)
{
sum[i][0]=sum[i-1][0]+n[i][0];
sum[i][i]=sum[i-1][i-1]+n[i][i];
}
而初始化第一项和特殊项之后,也可以发现普通项是从sum[2][1]开始,既可以从上方来,也可以从左上方来,题目要求最大路径和,所以此时需要判断哪条路来的路径和最大,此时可以使用:
for(int i=2;i<N;i++)
{ //小于i是因为最后一列已经初始化了,不需要更改
for(int j=1;j<i;j++)//而且数字三角形的最后一列是和行相等的
{
sum[i][j]=sum[i-1][j]>sum[i-1][j-1]?sum[i-1][j]:sum[i-1][j-1];
//判断哪条路径来的路径和最大
sum[i][j]+=n[i][j];
//不要忘记加上路径到达这里的数字
}
}
最后判断最后一行哪个数字最大,就是从最上面到最下面最大路径和了。
上完整代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int N,max=0;
cin >> N;
int n[N][N]={0};
for(int i=0;i<N;i++)
{
for(int j=0;j<i+1;j++)
{
cin >> n[i][j];
}
}
int sum[N][N]={0};
//到n[i][j]时,最大路径和是sum[i][j]=max(sum[i-1][j],sum[i-1][j-1])+n[i][j]
//sum[N-1][j]是要的答案
//初始化
sum[0][0]=n[0][0];
for(int i=1;i<N;i++)
{
sum[i][0]=sum[i-1][0]+n[i][0];
sum[i][i]=sum[i-1][i-1]+n[i][i];
}
for(int i=2;i<N;i++)
{ //小于i是因为最后一列已经初始化了,不需要更改
for(int j=1;j<i;j++)//而且数字三角形的最后一列是和行相等的
{
sum[i][j]=sum[i-1][j]>sum[i-1][j-1]?sum[i-1][j]:sum[i-1][j-1];
//判断哪条路径来的路径和最大
sum[i][j]+=n[i][j];
//不要忘记加上路径到达这里的数字
}
}
for(int j=0;j<N;j++)//找最大路径和
{
if(sum[N-1][j]>max)
{
max=sum[N-1][j];
}
}
cout << max;
return 0;
}