洛谷 P1216 数字三角形
题目链接:数字三角形
思路
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数组取最大值即可得到结果。
代码
#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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步