【动态规划】路径问题 {二维动态规划;选择合适的状态表示方法;创建虚拟节点}

本文主要是介绍【动态规划】路径问题 {二维动态规划;选择合适的状态表示方法;创建虚拟节点},希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、经验总结

选择合适的状态表示方法
一般的,状态表示的方法有两种:

  1. 以[i, j]位置为终点,正向填表;用之前的状态推导出dp[i][j]的值(从哪里来);
  2. 以[i, j]位置为起点,反向填表;用之后的状态推导出dp[i][j]的值(到哪里去);

创建虚拟节点

  • 一般虚拟节点设置在需要特殊处理的边界位置,在二维动态规划中,可以出现在矩阵的四边。
  • 需要根据题目要求设置虚拟节点的初始值,以确保后续填表的正确性。
  • 注意dp表与原始表的下标映射关系。

二、相关编程题

2.1 不同路径

题目链接

62. 不同路径 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:int uniquePaths(int m, int n) {vector<vector<int>> dp(m+1, vector<int>(n+1, 0)); //多开一行一列作为虚拟节点dp[0][1] = 1; //虚拟节点的初始值,保证后续填表的正确性for(int i = 1; i <= m; ++i) //从上往下{for(int j = 1; j <= n; ++j) //从左往右{dp[i][j] = dp[i-1][j] + dp[i][j-1];}}return dp[m][n];}
};

2.2 不同路径Ⅱ

题目链接

63. 不同路径 II - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obs) {int m = obs.size(), n = obs[0].size();vector<vector<int>> dp(m+1, vector<int>(n+1, 0));dp[0][1] = 1;for(int i = 1; i <= m; ++i){for(int j = 1; j <= n; ++j){if(obs[i-1][j-1] == 1) continue; //注意dp表与原矩阵下标的映射关系dp[i][j] = dp[i-1][j] + dp[i][j-1];}}return dp[m][n];}
};

2.3 珠宝的最高价值

题目链接

LCR 166. 珠宝的最高价值 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:int jewelleryValue(vector<vector<int>>& frame) {int m = frame.size(), n = frame[0].size();vector<vector<int>> dp(m+1, vector<int>(n+1));for(int i = 1; i <= m; ++i){for(int j = 1; j <= n; ++j){dp[i][j] = max(dp[i][j-1], dp[i-1][j])+frame[i-1][j-1];}}return dp[m][n];}
};

2.4 下降路径最小和

题目链接

931. 下降路径最小和 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:int minFallingPathSum(vector<vector<int>>& matrix) {int n = matrix.size();vector<vector<int>> dp(n+1, vector<int>(n+2, INT_MAX)); //dp表多创建1行2列for(int j = 0; j < n+2; ++j) //将第一行(虚拟节点)初始化为0,两边的两列初始化为INT_MAX{dp[0][j] = 0;}auto min = [](int a, int b, int c)->int{int tmp = a<b? a:b;return c<tmp? c:tmp;};for(int i = 1; i <= n; ++i) //从上往下填表{for(int j = 1; j <= n; ++j){dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i-1][j+1])+matrix[i-1][j-1];}}int ret = INT_MAX; //选出最后一行的最小值作为结果for(int j = 1; j <= n; ++j){if(ret>dp[n][j]){ret = dp[n][j];}}return ret;}};

2.5 最小路径和

题目链接

64. 最小路径和 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:int minPathSum(vector<vector<int>>& grid) {int m = grid.size(), n = grid[0].size();vector<vector<int>> dp(m+1, vector<int>(n+1, INT_MAX));dp[0][1] = dp[1][0] = 0;for(int i = 1; i <= m; ++i){for(int j = 1; j <= n; ++j){dp[i][j] = grid[i-1][j-1] + min(dp[i-1][j], dp[i][j-1]);}}return dp[m][n];}
};

2.6 地下城游戏

题目链接

174. 地下城游戏 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

本题的难点在于怎么处理血量增加的问题, 增加血量不能为之前的损失提供帮助,只会对后续有帮助。
这意味着正向填表是困难的,但是反向填表很好做。以当前位置为起点,从后往前推,当前如果可以治愈,那么当前的最低血量就是下一关的最低血量减去治疗量,注意不可以<1。

编写代码

class Solution {
public:int calculateMinimumHP(vector<vector<int>>& dun) {int m = dun.size(), n = dun[0].size();vector<vector<int>> dp(m+1, vector<int>(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]) - dun[i][j];dp[i][j] = max(1, dp[i][j]);}}return dp[0][0];}
};

这篇关于【动态规划】路径问题 {二维动态规划;选择合适的状态表示方法;创建虚拟节点}的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1080911

相关文章

如何选择适合孤独症兄妹的学校?

在探索适合孤独症儿童教育的道路上,每一位家长都面临着前所未有的挑战与抉择。当这份责任落在拥有孤独症兄妹的家庭肩上时,选择一所能够同时满足两个孩子特殊需求的学校,更显得尤为关键。本文将探讨如何为这样的家庭做出明智的选择,并介绍星贝育园自闭症儿童寄宿制学校作为一个值得考虑的选项。 理解孤独症儿童的独特性 孤独症,这一复杂的神经发育障碍,影响着儿童的社交互动、沟通能力以及行为模式。对于拥有孤独症兄

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<

hdu1565(状态压缩)

本人第一道ac的状态压缩dp,这题的数据非常水,很容易过 题意:在n*n的矩阵中选数字使得不存在任意两个数字相邻,求最大值 解题思路: 一、因为在1<<20中有很多状态是无效的,所以第一步是选择有效状态,存到cnt[]数组中 二、dp[i][j]表示到第i行的状态cnt[j]所能得到的最大值,状态转移方程dp[i][j] = max(dp[i][j],dp[i-1][k]) ,其中k满足c

hdu2544(单源最短路径)

模板题: //题意:求1到n的最短路径,模板题#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#i

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表