这道题题意很简单,直接说思路吧。
可以 Dp、递推,递推容易理解,时间复杂度低,递推优于 Dp。
先讲一下 Dp :
开一个dp[ ][ ] 数组, dp[i][j] 意味着牛走到第 i 行 , 第 j 个点的最优值。
从第一行开始分别取每个点的最优值,每个点的值都不为负, 所以列出下式:
dp[i][j] = max(dp[i-1][j-1] + m[i][j], dp[i-1][j] + m[i][j]);
第 i 行 , 第 j 个点的最优值等于:
(上一行 第 j个点的最优值 + 自身)、 (上一行 第 j -1个点的最优值 + 自身)两者中的最优值。
注意(每一行第一个点需特殊考虑, 初始化 dp [] []数组全为0,可不特殊考虑,个人喜好而定)
代码:
#include <iostream>
#include <cstring>
const int N = 360;
int dp[N][N], m[N][N];
// dp[i][j] 意味着牛走到第 i 行 , 第 j 个点的最优值。
// m[i][j] 第 i 行 , 第 j 个点的值
using namespace std;
int main()
{
int n;
cin >> n;
for (int i=1; i<=n; i++)
{
for (int j=1; j<=i; j++)
cin >> m[i][j]; // 输入每个点的值
}
memset (dp, 0, sizeof(dp)); //初始化
dp[1][1] = m[1][1];
for(int i=2; i<n; i++)
{
dp[i][1] = dp[i-1][1] + m[i][1];
for(int j=2; j<=i; j++)
{
dp[i][j] = max(dp[i-1][j-1]+m[i][j], dp[i-1][j]+m[i][j]);
//上一行 第 j个点的最优值 + 自身)、 (上一行 第 j -1个点的最优值 + 自身)两者中的最优值
}
}
dp[n][1] = dp[n-1][1] + m[n][1];
int ans =dp[n][1]; // 最优结果
for(int j=2; j<=n; j++)
{
dp[n][j] = max(dp[n-1][j]+m[n][j], dp[n-1][j-1]+m[n][j]);
if(dp[n][j] > ans)
ans = dp[n][j];
}
cout << ans << endl;
return 0;
}
递推:
从最后一行向上推,更新每个点的值,倒着思考(终点为第一行 第一个点)。
举一个例子:a[i][j] += max(a[i+1][j],a[i+1][j+1]);
第 i 行, 第 j 点 (i<n) 只能走到 第 i+1行 j 点 j+1 两点
若要更新第 i 行, 第 j 点肯定是这两点 (第 i+1行 j 点 j+1点)到这点(第 i 行, 第 j 点)的最优值。
代码:
#include<stdio.h>
int a[400][400]; // 存储每个点的值
int max(int a,int b)
{
if(a>b) return a;
return b;
}
int main()
{
int i, j, n;
scanf("%d",&n);
for(i=1; i<=n; i++)
for(j=1; j<=i; j++)
{
scanf("%d",&a[i][j]); // 输入地图
}
for(i=n-1; i>=1; i--)
{
for(j=1; j<=i; j++)
{
a[i][j] += max(a[i+1][j],a[i+1][j+1]); // 从下往上依次更新
}
}
printf("%d",a[1][1]);
return 0;
}