IOI(1994)数字三角形
2026-05-20 07:18:49
发布于:广东
这么简单?
题目:
Description
观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
图片地址https://cdn.vjudge.net.cn/a1379badc4b471eb2465a562cf6eb828?3
在上面的样例中,从 7→3→8→7→5 的路径产生了最大权值。
Input
第一个行一个正整数 r,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
Output
单独的一行,包含那个可能得到的最大的和。
Input
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
Output
30
Hint
【数据范围】
对于 100% 的数据,1≤r≤1000,所有输入在[0,100] 范围内。
题目翻译来自 NOCOW。
IOI1994 Day1T1 / USACO Training Section 1.5。
是不是非常简单,用滑膛(线性)大炮(dp)就行了。
思路
方法自底向上一维 DP
状态转移方程
dp[i][j] = max(dp[i+1][j], dp[i+1][j+1]) + a[i][j]
边界条件
最后一行的节点到底部的最大路径和就是自身:dp[r][j] = a[r][j]
最终结果
顶部节点dp[1][1]即为答案(从顶部到底部的最大路径和)。
注意:动态规划的核心是状态定义和状态转移方程,本题通过定义到达每个节点的最大路径和,将问题分解为子问题求解。
时间复杂度:O(r²)
空间复杂度:O(r)
代码
#include<bits/stdc++.h>
using namespace std;
int main() {
int r;
cin >> r;
vector<vector<int>> a(r + 1, vector<int>(r + 1));
vector<int> dp(r + 2, 0);
for (int i = 1; i <= r; ++i) {
for (int j = 1; j <= i; ++j) {
cin >> a[i][j];
}
}
for (int j = 1; j <= r; ++j) {
dp[j] = a[r][j];
}
for (int i = r - 1; i >= 1; --i) {
for (int j = 1; j <= i; ++j) {
dp[j] = max(dp[j], dp[j+1]) + a[i][j];
}
}
cout << dp[1] << endl;
return 0;
}
这里空空如也

















有帮助,赞一个