数据结构与算法学习笔记----线性DP
@@ author: 明月清了个风
@@ first publish time: 2025.2.15
ps⭐️包含了几种常见的线性DP模型------数字三角形,最长上升子序列,最长公共子序列,最短编辑距离。给出了具体思路及证明过程和一些题目代码优化的过程,题目较多。
线性动态规划 (Linear Dynamic Programming,简称线性DP)是动态规划问题中的一种常见类型,其特点是状态转移方程中的状态是线性排列的,通常可以通过一维或二维数组来表示状态。线性DP问题通常具有明显的阶段性,每个阶段的状态只依赖于前一个或前几个阶段的状态。
线性DP的基本思路
- 定义状态 :根据问题的特点,定义状态表示。通常状态可以表示为一个一维或二维数组,例如
dp[i]
或dp[i][j]
。 - 状态转移方程:找到状态之间的关系,即如何从已知状态推导出新的状态。状态转移方程是线性DP的核心。
- 初始化 :确定初始状态的值,通常是
dp[0]
或dp[0][0]
等。 - 计算顺序:按照一定的顺序计算状态,通常是从小到大或从前往后。
- 结果:根据问题的要求,从最终的状态中提取结果。
上一篇中的01背包问题,其实也是一个典型的线性DP问题。
Acwing 898. 数字三角形
原题链接\]([898. 数字三角形 - AcWing题库](https://www.acwing.com/problem/content/900/))
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
```cpp
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
```
#### 输入格式
第一行包含整数 n n n,表示数字三角形的层数
接下来 n n n行,每行包含若干整数,其中第 i i i行表示数字三角形第 i i i层包含的整数。
#### 输出格式
输出一个整数,表示最大的路径数字和。
#### 数据范围
1 ≤ n ≤ 500 1 \\le n \\le 500 1≤n≤500,
− 1000 ≤ 三角形中的整数 ≤ 10000 -1000 \\le 三角形中的整数 \\le 10000 −1000≤三角形中的整数≤10000、
#### 思路
这是线性DP中的一道经典题,直接来看状态表示和状态计算方法:
对于状态表示,使用`f[i][j]`,它表示的集合是所有从起点走到`(i, j)`这个点的路径,我们需要求的属性值是这个集合中的最大值。
对于状态计算,我们将`f[i][j]`所表示的集合划分为两类:从左上方走下来的路径和从右上方走下来的路径。对于从左上方走下来的路径,当前点`a[i, j]`排除后,上一层状态就是`f[i - 1][j - 1] + a[i][j]`;对于从右上方走下来的路径,我们同理可以写成`f[i - 1][j] + a[i][j]`(这里是把整个矩阵看成下面这个形状了)
```cpp
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
```
动态规划的时间复杂度计算其实比较抽象,这里给出y总教的------状态数×转移计算量。在这一题中,状态数量就是 n 2 n\^2 n2,转移计算量是 O ( 1 ) O(1) O(1)的,因此时间复杂度就是 O ( n 2 ) O(n\^2) O(n2)。
下面就来看代码吧,代码中有个注意点,也是动态规划问题中的注意点,需要对初始状态进行初始化,并且每道题的初始化都会不一样,需要根据要求的东西进行,比如这里我们要求的是最大值,因此需要初始化为负无穷,并且在初始化时,需要注意所有要用到的状态都需要初始化(代码中注释的地方)
#### 代码
```cpp
#include