洛谷 P1216 數字三角形

薛定谔的AC發表於2024-06-16

題目連結:數字三角形



思路

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;
}

相關文章