本题可用递推法和递归法。
其状态转移方程为:dp[i][j] = num_of_power[i][j] + max(dp[i + 1][j], dp[i + 1][j + 1]);
1(递推法):
使用递推方式,从数塔底部往上推,关键是要注意边界和计算的顺序。
Time:46MS Memory:1656K
代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int num_of_power[105][105];
int dp[105][105];
int n;
int main() {
int c;
int maxnum;
scanf("%d", &c);
while (c--) {
scanf("%d", &n);
for (int i = 0; i <n; i++)
for (int j = 0; j <=i; j++)
scanf("%d", &num_of_power[i][j]);
for (int j = 0; j < n; j++) dp[n-1][j] = num_of_power[n-1][j];
for (int i = n - 2; i >= 0; i--)
for (int j = 0; j <= i; j++)
dp[i][j] = num_of_power[i][j] + max(dp[i + 1][j], dp[i + 1][j + 1]);
printf("%d\n", dp[0][0]);
}
return 0;
}
2.(递归法):
关键点还是要注意边界,还需要用上记忆化搜索,代码为if (dp[i][j] > 0) return dp[i][j];这样可以避免走重复的结点。
Time:62MS Memory:1656K
代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int num_of_power[105][105];
int dp[105][105];
int n;
int solve(int i, int j) {
if (dp[i][j] > 0) return dp[i][j];
return dp[i][j] = num_of_power[i][j] + (i == n ? 0 : max(solve(i + 1, j), solve(i + 1, j + 1)));
}
int main() {
int c;
scanf("%d", &c);
while (c--) {
scanf("%d", &n);
for (int i = 0; i <n; i++)
for (int j = 0; j <= i; j++)
scanf("%d", &num_of_power[i][j]);
memset(dp, -1, sizeof(dp));
int maxnum = solve(0, 0);
printf("%d\n", maxnum);
}
return 0;
}