DP问题概述
DP路径问题
- DP的关键问题在于寻找整个问题当中是否存在(初始状态,转移状态,状态转移方程)等等关键的key,当我们能够寻找到这些key的时候,那么本问题也能够用dp解决。
- DP关键在于找到状态转移方程(重中之重)。
路径的回溯问题
- 路径的回溯问题的关键在于能够将回来时的每一步都“记录在案”,然后逆序输出出来,这个问题的解析在点这里。DP路径还涉及到一些跟图算法相关的知识,相关的牵连在上面的链接里面也能够看得到。
- dp问题当中的三角路径最短问题,重要的是找到:(状态初始值,转移状态,状态方程)。确定问题前后之间满足”无后效性“的客观定义,使用dp解决问题,空间大小使用滚动数组节省空间。
- dp路径的问题最初的demo应该是“一个起点,一个终点”,这个是最简单的模型,再到后面延伸复杂的问题应该包含以下几个方面:
1.一个出发点,多个终点的情况(也就是到达最后一个行或者最后一列的情况),三角路径问题和自顶向下一个终点的问题的变种。
2.多个出发点,多个终点的情况,也就是下降路径问题,一般的解决方案会比之前的一个起点,多个终点的方案多一个空间维度,所以它的空间复杂度在\(O(n^3)\)。可以借助滚动数组方案进行优化工作。空间复杂度一般会降低一个维度。
class Solution {
int MAX = Integer.MAX_VALUE;
public int minFallingPathSum(int[][] mat) {
int n = mat.length;
int[][] f = new int[n][n];
// 初始化:对于首行而言,每个位置的「最小成本」就是其「矩阵值」
for (int i = 0; i < n; i++) f[0][i] = mat[0][i];
// 从第二行开始,根据题目给定的条件进行转移
for (int i = 1; i < n; i++) {
for (int j = 0; j < n; j++) {
int val = mat[i][j];
f[i][j] = f[i - 1][j] + val;
if (j - 1 >= 0) f[i][j] = Math.min(f[i][j], f[i-1][j-1] + val);
if (j + 1 < n) f[i][j] = Math.min(f[i][j], f[i-1][j+1] + val);
}
}
int ans = MAX;
for (int i = 0; i < n; i++) ans = Math.min(ans, f[n-1][i]);
return ans;
}
}
抬起头,永远年轻,永远热泪盈眶!