网站框架方案,wordpress播放上传视频,家居网站建设 百度文库,建筑企业入渝备案查询目录 一、63. 不同路径 II1.1 题目解析1.2 状态转移方程1.3 解题代码 二、931. 下降路径最小和2.1 题目解析2.2 状态转移方程2.3 解题代码三、174. 地下城游戏3.1 题目解析3.2 状态转移方程3.3 解题代码 一、63. 不同路径 II
题目地址#xff1a; 不同路径 II 一个机器人位于… 目录 一、63. 不同路径 II1.1 题目解析1.2 状态转移方程1.3 解题代码 二、931. 下降路径最小和2.1 题目解析2.2 状态转移方程2.3 解题代码三、174. 地下城游戏3.1 题目解析3.2 状态转移方程3.3 解题代码 一、63. 不同路径 II
题目地址 不同路径 II 一个机器人位于一个 m x n 网格的左上角 起始点在下图中标记为 “Start” 。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角在下图中标记为 “Finish”。 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径 网格中的障碍物和空位置分别用 1 和 0 来表示。 输入obstacleGrid [[0,0,0],[0,1,0],[0,0,0]] 输出2 解释3x3 网格的正中间有一个障碍物。 从左上角到右下角一共有 2 条不同的路径 向右 - 向右 - 向下 - 向下向下 - 向下 - 向右 - 向右 1.1 题目解析
状态表示
对于这种「路径类」的问题我们的状态表示⼀般有两种形式
从 [i, j]位置出发到达⽬标位置有多少种方式从起始位置出发到达 [i, j]位置⼀共有多少种方式。
这⾥选择第⼆种定义状态表示的方式dp[i][j]表示走到 [i, j]位置处⼀共有多少种方式。
状态转移
简单分析⼀下。如果 dp[i][j]表示到达 [i, j]位置的方法数那么到达 [i, j]位置之前的⼀小步有两种情况
从 [i, j]位置的上方 [i - 1, j]的位置向下走一步转移到 [i, j]位置从 [i, j]位置的左方 [i, j - 1]的位置向右⾛⼀步转移到 [i, j]位置。
但是 [i - 1, j]与 [i, j - 1]位置都是可能有障碍的此时从上⾯或者左边是不可能到达 [i, j]位置的也就是说此时的方法数应该是 0。由此我们可以得出⼀个结论只要这个位置上「有障碍物」那么我们就不需要计算这个位置上的值直接让它等于 0 即可。
初始化
可以在最前⾯加上⼀个「辅助结点」帮助我们初始化。使⽤这种技巧要注意两个点
辅助结点⾥⾯的值要「保证后续填表是正确的」「下标的映射关系」。
在本题中添加一行并且添加⼀列后只需将 dp[1][0]的位置初始化为 1即可。 添加一行和一列是因为[i, j]位置需要[i - 1, j]和[i, j - 1]两个方位的值以此确保状态表不越界将dp[1][0]初始化为1为了保证在起点时有方法数 1 。
填表顺序
根据「状态转移」的推导填表的顺序就是 「从上往下」填每一行每一行「从左往右」。
返回值
根据「状态表⽰」我们要返回的结果是 dp[m][n]。
1.2 状态转移方程
从当前位置的上方和左方到达当前位置的方法数dp[i][j] dp[i - 1][j] dp[i][j - 1];。还需要注意的是若当前位置为障碍物直接将当前状态置为0(即dp[i][j] 0;)
1.3 解题代码
class Solution
{
public:int uniquePathsWithObstacles(vectorvectorint obstacleGrid) {int row obstacleGrid.size(), col obstacleGrid[0].size();//1. 创建dp表vectorvectorint dp(row 1, vectorint(col 1));//2. 初始化dp[0][1] 1;//3. 填表//从上到下填表 - 从左到右填表for (int i 1; i row; i)for (int j 1; j col; j)if(obstacleGrid[i - 1][j - 1] 0) dp[i][j] dp[i][j - 1] dp[i - 1][j];//4. 返回值return dp[row][col];}
};二、931. 下降路径最小和
题目地址 931. 下降路径最小和 给你一个n x n的 方形 整数数组 matrix 请你找出并返回通过 matrix 的下降路径 的 最小和。 下降路径 可以从第一行中的任何元素开始并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列即位于正下方或者沿对角线向左或者向右的第一个元素。具体来说位置(row, col) 的下一个元素应当是(row 1, col - 1)、(row 1, col)或者 (row 1, col 1) 。 输入matrix [[2,1,3],[6,5,4],[7,8,9]] 输出13 解释如图所示为和最小的两条下降路径 2.1 题目解析
状态表示
对于这种「路径类」的问题我们的状态表示一般有两种形式
从 [i, j] 位置出发到达⽬标位置有多少种方式从起始位置出发到达 [i, j] 位置⼀共有多少种方式
这里选择第⼆种定义状态表示的方式 dp[i][j]表示到达 [i, j]位置时所有下降路径中的最小和。
状态转移
对于普遍位置 [i, j]根据题意得到达 [i, j]位置可能有三种情况
从正上方 [i - 1, j]位置转移到 [i, j]位置从左上方 [i - 1, j - 1]位置转移到 [i, j]位置从右上方 [i - 1, j 1]位置转移到 [i, j]位置
我们要的是三种情况下的「最小值」然后再加上矩阵在 [i, j]位置的值。于是 dp[i][j] min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j 1])) matrix[i][j] 。
初始化
可以在最前⾯加上⼀个「辅助结点」帮助我们初始化。使用这种技巧要注意两个点
辅助结点里面的值要「保证后续填表是正确的」「下标的映射关系」。
事实上这题的状态转移方程是不难想到的而关键问题在于初始化。[i, j]位置的值可以从三个方向来 - 上、左、右所以为了不越界在本题中需要「加上一行」并且「加上两列」(最左边和最右边)。 所有的位置都初始化为无穷大然后将第一行初始化为 0 即可。将初始值设为无穷大是因为这些是虚拟节点不应该对选数造成影响(即大于其他两路的值)。
填表顺序
根据「状态表示」填表的顺序是「从上往下」。
返回值
注意这里不是返回 dp[m][n]的值 题⽬要求「只要到达最后一行」就行了因此这⾥应该返回「 dp 表中最后一行的最小值」。
2.2 状态转移方程
dp[i][j] min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j 1])) matrix[i][j]; 。
2.3 解题代码
class Solution
{
public:int minFallingPathSum(vectorvectorint matrix) {//1. 创建dp表int row matrix.size(), col matrix.size();vectorvectorint dp(row 1, vectorint(col 2, INT_MAX));//2. 初始化列表//第一行变为0for(int i 0; i col 2; i) dp[0][i] 0;//3. 填表for(int i 1; i row; i)for(int j 1; j col; j)dp[i][j] matrix[i - 1][j - 1] min(min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i - 1][j 1]);//4. 返回结果int ans INT_MAX;for(int i 1; i col; i)ans min(ans, dp[row][i]);return ans;}
};三、174. 地下城游戏
题目地址 174. 地下城游戏 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下他会立即死亡。 有些房间由恶魔守卫因此骑士在进入这些房间时会失去健康点数若房间里的值为负整数则表示骑士将损失健康点数其他房间要么是空的房间里的值为 0要么包含增加骑士健康点数的魔法球若房间里的值为正整数则表示骑士将增加健康点数。 为了尽快解救公主骑士决定每次只 向右 或 向下 移动一步。 返回确保骑士能够拯救到公主所需的最低初始健康点数。 注意 任何房间都可能对骑士的健康点数造成威胁也可能增加骑士的健康点数包括骑士进入的左上角房间以及公主被监禁的右下角房间。 输入dungeon [[-2,-3,3],[-5,-10,1],[10,30,-5]] 输出7 解释如果骑士遵循最佳路径右 - 右 - 下 - 下 则骑士的初始健康点数至少为 7 。 3.1 题目解析
状态表示
这道题如果我们定义成从起点开始到达 [i, j]位置的时候所需的最低初始健康点数。那么我们分析状态转移的时候会有⼀个问题那就是我们当前的健康点数还会受到后面的路径的影响。也就是从上往下的状态转移不能很好地解决问题。
这个时候我们要换⼀种状态表示从 [i, j]位置出发到达终点时所需要的最低初始健康点数。 这样我们在分析状态转移的时候后续的最佳状态就已经知晓。
综上所述定义状态表示为 dp[i][j]表示从 [i, j]位置出发到达终点时所需的最低初始健康点数。
状态转移方程
对于 dp[i][j]从 [i, j]位置出发下⼀步会有两种选择为了方便理解设 dp[i][j]的最终答案是 x
走到右边然后走向终点: 那么我们在 [i, j]位置的最低健康点数加上这⼀个位置的消耗应该要⼤于等于右边位置的最低健康点数也就是 x dungeon[i][j] dp[i][j 1]。通过移项可得 x dp[i][j 1] - dungeon[i][j]。因为我们要的是最小值因此这种情况下的 x dp[i][j 1] - dungeon[i][j]走到下边然后走向终点: 那么我们在 [i, j]位置的最低健康点数加上这⼀个位置的消耗应该要大于等于下边位置的最低健康点数也就是 x dungeon[i][j] dp[i 1][j]。通过移项可得 x dp[i 1][j] - dungeon[i][j]。因为我们要的是最小值因此这种情况下的 x dp[i 1][j] - dungeon[i][j]
综上所述我们需要的是两种情况下的最小值因此可得状态转移方程为dp[i][j] min(dp[i 1][j], dp[i][j 1]) - dungeon[i][j]
但是如果当前位置的 dungeon[i][j]是⼀个比较大的正数的话 dp[i][j]的值可能变成 0 或者负数。也就是最低点数会小于 1 那么骑士就会死亡。因此我们求出来的 dp[i][j]如果小于等于 0 的话说明此时的最低初始值应该为 1 。处理这种情况仅需让 dp[i][j]与 1 取⼀个最大值即可dp[i][j] max(1, dp[i][j])
初始化
可以在最前⾯加上⼀个「辅助结点」帮助我们初始化。使用这种技巧要注意两个点
辅助结点⾥⾯的值要「保证后续填表是正确的」「下标的映射关系」。
在本题中在 dp 表最后⾯添加一行并且添加⼀列后所有的值都先初始化为⽆穷大然后让dp[m][n - 1] dp[m - 1][n] 1即可。
填表顺序
根据「状态转移方程」我们需要「从下往上填每一行」「每一行从右往左」。
返回值
根据「状态表示」我们需要返回 dp[0][0]的值。
3.2 状态转移方程
骑士到达当前位置最低健康点数dp[i][j] min(dp[i 1][j], dp[i][j 1]) - dungeon[i][j] 确保健康值不低于1dp[i][j] max(1, dp[i][j]);
3.3 解题代码
class Solution
{public:int calculateMinimumHP(vectorvectorint dungeon) {int m dungeon.size(), n dungeon[0].size();// 建表 初始化vectorvectorint dp(m 1, vectorint(n 1, INT_MAX));dp[m][n - 1] dp[m - 1][n] 1;// 填表for(int i m - 1; i 0; i--){for(int j n - 1; j 0; j--){dp[i][j] min(dp[i 1][j], dp[i][j 1]) - dungeon[i][j];dp[i][j] max(1, dp[i][j]);}}// 返回结果return dp[0][0];}
};