洛谷 P1216 数字三角形

题目链接:数字三角形



思路

       dp:金字塔顶的元素为起点,金字塔每行的最左侧数字只能从上一层的最左侧数字到达,如7 -> 3 -> 8 -> 2 -> 4,这些数字中的每一个(除起点7外)都只能从上一层的最左侧数字到达,递推公式为dp[i][1] = max(dp[i][1], num[i][1] + dp[i - 1][1],最右侧数字同理,递推公式为dp[i][i] = max(dp[i][i], num[i][i] + dp[i - 1][i - 1],而中间的数字可以由上层相邻的两个数字到达,递推公式为dp[i][j] = max(dp[i][i], num[i][j] + dp[i - 1][j - 1], num[i][j] + dp[i - 1][j]
       优化:由于存储时使用的边界值为1,所以金字塔的最左侧和最右侧的数字的递推公式可以统一为dp[i][j] = max(dp[i][i], num[i][j] + dp[i - 1][j - 1], num[i][j] + dp[i - 1][j],然后发现每次递推时只需要使用两层的数据,所以将空间复杂度优化为O(2 * n),然后每次使用第一层计算出第二层之后,第一层的dp数组就不会再被使用,此时将第二层的dp数组赋值给第一层的dp数组,再用此时的第一层的dp数组计算出第二层的dp数组,一直递推即可得到第r层的dp数组,然后再对第r层的dp数组取最大值即可得到结果。
image


代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 10;
int dp[2][N], num[N];
int main() {
  int r;
  cin >> r;
  for (int i = 1; i <= r; i++) {
    for (int j = 1; j <= i; j++) {
        cin >> num[j];
    }
    for (int j = 1; j <= i; j++) {
      dp[1][j] = num[j] + max(dp[0][j], dp[0][j - 1]);
    }
    swap(dp[0], dp[1]);
  }

  int res = 0;
  for (int i = 1; i <= r; i++) {
    res = max(res, dp[0][i]);
  }

  cout << res  << endl;

  return 0;
}
posted @ 2024-06-16 13:24  薛定谔的AC  阅读(5)  评论(0编辑  收藏  举报