HDU 2084 是數塔(三角形)最大路徑和問題:從頂點到底邊,每步只能走左下或右下,求路徑最大和。
三角形第 i 行有 i 個數。設 dp[i][j] 為從頂點走到位置 (i,j) 的最大和。
dp[i][j] = max(dp[i-1][j-1], dp[i-1][j]) + val[i][j] 邊界條件: j = 1: dp[i][1] = dp[i-1][1] + val[i][1] (只能從左上來) j = i: dp[i][i] = dp[i-1][i-1] + val[i][i] (只能從右上來) 1 < j < i: dp[i][j] = max(dp[i-1][j-1], dp[i-1][j]) + val[i][j]
從倒數第二行向上更新,直接在原陣列上操作,空間 O(1) 額外空間:
for (int i = n-1; i >= 1; --i) {
for (int j = 1; j <= i; ++j) {
a[i][j] += max(a[i+1][j], a[i+1][j+1]);
}
}
答案在 a[1][1]
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 105;
int a[MAXN][MAXN];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= i; ++j)
cin >> a[i][j];
// 自底向上 DP
for (int i = n - 1; i >= 1; --i) {
for (int j = 1; j <= i; ++j) {
a[i][j] += max(a[i+1][j], a[i+1][j+1]);
}
}
cout << a[1][1] << '\n';
}
return 0;
}
max 改為 mincnt[i][j] = (左大?cnt左:0) + (右大?cnt右:0)數塔問題是動態規劃入門的最佳範例,理解其狀態定義、轉移邏輯與優化技巧,為解決更複雜的 DP 問題打下堅實基礎。