題目鏈接:https://vjudge.net/problem/HDU-2084
思路1:從上往下遞推
dp[i][j]表示第i層第j個節點經過結點的數字之和的最大的值。
狀態轉移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+a[i][j]。對j==1與j==i進行特判
代碼:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
int a[maxn][maxn], dp[maxn][maxn];
int main() {
int C, N;
scanf("%d", &C);
while (C--) {
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= i; j++) {
scanf("%d", &a[i][j]);
}
}
memset(dp,0,sizeof(dp));
dp[1][1] = a[1][1];
for (int i = 2; i <= N; i++) {
for (int j = 1; j <= i; j++) {
if (j == 1) dp[i][j] = dp[i - 1][1] + a[i][j];
else if (j == i) dp[i][j] = dp[i - 1][j-1] + a[i][j];
else {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + a[i][j];
}
}
}
int ans = -1;
for (int i = 1; i <= N; i++) {
ans = max(ans, dp[N][i]);
}
cout << ans << endl;
}
return 0;
}
思路2:從下往上遞推
討論:我們要得到“經過結點的最大數字之和”,路徑的首與尾是確定的,首是第一層的頭節點,尾一定是在第n層節點。
我們這裏設定dp[0][0]爲我們要求的答案,也即從尾出發走到頭。
狀態轉移方程:dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+dp[i][j];
代碼:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
int dp[maxn][maxn];
int C, N;
int main() {
scanf("%d", &C);
while (C--) {
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= i; j++) {
scanf("%d", &dp[i][j]);
}
}
for (int i = N - 1; i >= 1; i--) {
for (int j = 1; j <= i; j++) {
dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + dp[i][j];
}
}
cout << dp[1][1] << endl;
}
return 0;
}