当前位置:网站首页>一本通1258.数字金字塔 题解 动态规划
一本通1258.数字金字塔 题解 动态规划
2022-06-10 06:34:00 【51CTO】
题目链接: http://ybt.ssoier.cn:8088/problem_show.php?pid=1258
题目大意:
给你一个数字金字塔,每次可以从当前点走到左下方或右下方的点。查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。
解题思路:
设 \(a_{i,j}\) 表示数字金字塔上第 \(i\) 行从左往右数第 \(j\) 个点,则我们的目的就是从 \(a_{1,1}\) 走到第 \(n\) 行的 \(a_{n,i}\)(此处 \(i\) 可能是 \(1 \sim n\) 范围内的任何一个点)。
很明显这道题目可以用动态规划(DP)求解,但是根据求解的方向不同,对应的状态也不相同。
这里,我们可以以两种思路来解决这个问题:
- 第1种思路:自顶向下(从上往下推);
- 第2种思路:自底向上(从下往上推)。
下面,我们来依次分析两种思路。
自顶向下(从上往下推)
定义状态 \(f_{i,j}\) 表示从 \(a_{1,1}\) 走到 \(a_{i,j}\) 的所有路径数字和的最大值。则,可以推导出状态转移方程为:
- 当 \(i =1\) 时(\(i=1\) 时只有一个状态 \(f_{1,1}\)),\(f_{1,1} = a_{1,1}\);
- 当 \(i \gt 1\) 时,
- 当 \(j = 1\) 时,\(f_{i,1} = f{i-1,1} + a_{i,1}\)(最左边的点只能从右上方走过来);
- 当 \(j = i\) 时,\(f_{i,i} = f{i-1,i-1} + a_{i,i}\)(最右边的点只能从左上方走过来);
- 当 \(1 \lt j \lt i\) 时,\(f_{i,j} = \max\{f_{i-1,j-1}f_{i-1,j}\} + a_{i,j}\)(中间的点可以选择从左上角或右上角的点走过来,所以选择两者的较大值)
令 \(i = 1 \rightarrow n\) 的顺序推导出所有的 \(f_{i,j}\),则最终的答案就是:
- \(f_{n,1}\)(从 \(a_{1,1}\) 走到 \(a_{n,1}\) 的最大数字和)、
- \(f_{n,2}\)(从 \(a_{1,1}\) 走到 \(a_{n,2}\) 的最大数字和)、
- \(f_{n,3}\)(从 \(a_{1,1}\) 走到 \(a_{n,3}\) 的最大数字和)、
- …… ……
- \(f_{n,n}\)(从 \(a_{1,1}\) 走到 \(a_{n,n}\) 的最大数字和)
的最大值,即答案为 \(\max\{ f_{n,i} \}\)(其中 \(i \in [1,n]\))
说明:\(\in\) 是“属于”符号,\(i \in [1,n]\) 表示 \(i\) 属于 \([1,n]\) 范围内,即 \(i\) 是 \(1\) 到 \(n\) 范围内(包括 \(1\) 和 \(n\))的一个整数。
按照自顶向下实现的代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int n, a[maxn][maxn], f[maxn][maxn], ans;
int main()
{
scanf("%d", &n); // 虽然题目里用R表示行的数量,但是我还是比较习惯用n表示行数
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= i; j ++)
scanf("%d", &a[i][j]);
for (int i = 1; i <= n; i ++)
{
for (int j = 1; j <= n; j ++)
{
if (i == 1) f[i][j] = a[i][j];
else if (j == 1) f[i][j] = f[i-1][j] + a[i][j];
else if (j == i) f[i][j] = f[i-1][j-1] + a[i][j];
else f[i][j] = max(f[i-1][j-1], f[i-1][j]) + a[i][j];
}
}
for (int i = 1; i <= n; i ++)
ans = max(ans, f[n][i]);
printf("%d\n", ans);
return 0;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
自底向上(从下往上推)
从第 \(1\) 行的格子(\(a_{1,1}\))走到第 \(n\) 行的路径的最大数字和,等价于从第 \(n\) 行选一个点作为起点从下往上走到 \(a_{1,1}\) 的路径最大数字和。所以我们可以把问题看成从下往上走找一条最大路径的数字和。
那么我们可以定义状态 \(f_{i,j}\) 表示:从第 \(n\) 行找一个点作为起点走到 \(a_{i,j}\) 的路径的最大数字和,则可以推导出转台转移方程为:
- 当 \(i = n\) 时,\(f_{i,j} = a_{i,j}\)(因为时最下面一行,起点出发能够得到的数字就是本身);
- 当 \(i \lt n\) 时,\(f_{i,j} = \max\{ f_{i+1,j} , f_{i+1,j+1} \} + a_{i,j}\)。
注意这里要按照 \(i = n \rightarrow 1\) 的方向推导出所有的状态。
则最终的状态为 \(f_{1,1}\)(因为从小往上推的话,所有路径对应的重点只有一个就是 \(a_{1,1}\))。
按照自底向上实现的代码如下(可以发现,按照这种方法实现的代码更简洁一些):
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int n, a[maxn][maxn], f[maxn][maxn];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= i; j ++)
scanf("%d", &a[i][j]);
for (int i = n; i >= 1; i --)
{
for (int j = 1; j <= i; j ++)
{
if (i == n) f[i][j] = a[i][j];
else f[i][j] = max(f[i+1][j], f[i+1][j+1]) + a[i][j];
}
}
printf("%d\n", f[1][1]);
return 0;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
边栏推荐
- Teacher lihongyi's notes on machine learning -5 transformer
- SQL practice part: SQL row column conversion and real problems
- tensorflow实验九----------泰坦尼克号
- TeleyeControlor V8.47版本发布 更改Socket框架
- QT上位机 通过EGM实时控制ABB
- 深度解析智能運維下告警關聯頻繁項集挖掘算法原理
- In depth understanding of exit vs \u exit
- Wechat team sharing: how the wechat background does not crash under massive concurrent requests
- Fix a button in the lower right corner
- Where will the alarm messages go? Fly in the flying book
猜你喜欢

Xshell下载安装使用简单教程

Stm32f1 and stm32subeide quick start - overview of interrupts, NVIC and exti

Saccadenet: use corner features to fine tune the two stage prediction frame | CVPR 2020

Tap series article 2 | Tanzu application platform v1.1 installation and configuration steps

OSPF route summary experiment

Leetcode-473. Match to square: a 4x15 queen problem (actually a backtracking method)

Leetcode-473. 火柴拼正方形:一个4X15的皇后问题(其实就是一个回溯法)

Model learning comprehension in Multi-Agent Reinforcement Learning Based on Model

TeleyeControlor V8.16发布 完成注册表功能

PM2 installation and common commands
随机推荐
BOM browser object model
Deploy MySQL based on statefulset in kubernetes (Part 2)
CMD of Jerry's AI protocol_ SET_ BLE_ Visibility [chapter]
SM2 state secret encryption and signing operation tool
sql基础
告警消息何去何从?在飞书中飞起来
TeleyeControlor V8.47版本发布 更改Socket框架
李宏毅老师《机器学习》课程笔记-4.2 Batch Normalization
How to convert text into numerical value in excel?
Rsync+inotify remote synchronization
深度解析智能運維下告警關聯頻繁項集挖掘算法原理
Common status codes
spark 避免对一个列重复解析json
Firefox browser settings point to proxy mode
Common regular applications
Leetcode-473. 火柴拼正方形:一个4X15的皇后问题(其实就是一个回溯法)
深度解析智能运维下告警关联频繁项集挖掘算法原理
tensorflow实验十-----图片翻转与缩放
Business topic: ab test experiment design and evaluation
Virtual machine network connection mode