数字三角形 题解

题意简述

题目链接

Vijos ETO P1001(推荐)
Acwing 898
Luogu P1216

题目描述

给定一个的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大

输入输出样例

输入样例

5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

输出样例

30

样例解释

在上面的样例中,从 7 → 3 → 8 → 7 → 5 7→3→8→7→5 73875 的路径产生了最大权值。

思路分析

贪心?

首先考虑是否可以贪心。

路径是不是需要经过最大值
容易构造一组反例。

输入:

3
1
2 100
99 0 0

如果经过最大值 100 100 100,那么最终结果为 101 101 101;但是如果不这样走,通过路径 1 → 2 → 99 1\to2\to99 1299,那么结果为 102 102 102,显然 102 > 101 102>101 102>101,所以这种贪心方法并不正确。

如果转而考虑次大值,次次大值,那么会在贪心的错误算法中越陷越深。此时,我们需要使用过其他的算法。

递归版动态规划(记忆化搜索)

爆搜

爆搜思路

既然贪心行不通,那么似乎没有什么好办法了,那么,我们可以考虑进行搜索,然后进行剪枝等优化。

爆搜代码
#include <iostream>
const int MAXN = 1e3 + 10;

int n, a[MAXN][MAXN];

int dfs(int x, int y) {
   
  if (x == n) return a[x][y]; // 边界条件
  return a[x][y] + std::max(dfs(x + 1, y), dfs(x + 1, y + 1));
  // 选择下一层的更大的计算出来的值加上当前值
}

int main() {
   
  std::cin >> n;
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= i; ++j)
      std::cin >> a[i][j];
  std::cout << dfs(1, 1) << std::endl;
  return 0;
}

当然,上面的代码可以等价变形为如下代码:

#include <iostream>
const int MAXN = 1e3 + 10;

int n, a[MAXN][MAXN];

int dfs(int x, int y) {
   
  return a[x][y] + (x == n ? 0 : std::max(dfs(x + 1, y), dfs(x + 1, y + 1)))
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三日连珠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值