题目链接: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;
}