您的位置:首页 > 房产 > 家装 > 动态规划算法:08.路径问题_下降路径最小和_C++

动态规划算法:08.路径问题_下降路径最小和_C++

2025/1/10 18:44:19 来源:https://blog.csdn.net/2302_76267737/article/details/142317870  浏览:    关键词:动态规划算法:08.路径问题_下降路径最小和_C++

题目链接:931. 下降路径最小和 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/minimum-falling-path-sum/description/

一、题目解析

题目:

解析:

题目告诉我们,我们可以从第一行任何一个元素开始,对其下方三个元素进行选择

我们拿示例一举例:

直到最后一行

二、算法原理

1、状态表示

我们在状态标识的时候,一般都会创建一个数组dp,也就是我们所说的dp表,我们要做的就是把每一个状态的值填入这个表内,最终这个表内的某一个值可能就是我们要返回的值。 

  状态简单理解就是dp表内某一个值代表的含义。

如何确定状态表示

  • 题目要求

   简单的题目里一般会给出

  • 经验+题目要求

  越学越深入,动态规划也是熟能生巧,在题目中没有明显给出的时候,我们就要凭借自己做题的经验来确定,所以就需要我们大量的做题。

  • 分析问题的过程中,发现重复子问题

 分析问题的过程中把重复子问题抽象成我们的状态表示,这个更难理解,一切的基础都是我们先对动态规划算法熟练运用。我也不懂,我们慢慢来。

综上:我们通常会以一个位置为结尾或者开始求得我们想要的答案

那我们的这道题得状态表示是什么样的:

根据经验,我们以一个位置为结尾做题

状态表示:dp[i][j]表示为,到达(i,j)位置时的路径和最小

2、状态转移方程

 确定状态表示之后我们就可以根据状态标识推出状态转移方程

  状态转移方程是什么?

不讲什么复杂的,简单来说状态转移方程就是    dp[i][j]等于什么 dp[i][j]=?

  这个就是状态转移方程,我们要做的,就是推出dp[i][j]等于什么

  我们根据状态表示再结合题目+经验去推理转移方程,这一步也是我们整个解题过程中最难的一步

  我们在这道题先简单了解下什么是状态转移方程,之后比较难的题目再细推

  状态转移方程推理:在我们之前做的题目中,求最短路径和、珠宝的最大价值,都是从一个位置向右或者向下,其实同理,我们这道题其实就是换了一个走路顺序,但是本质解题思路没有变。

  我们想要知道dp[i][j],也就是(i,j)位置的最小路径和,我们要清楚我们是怎么到达(i,j)位置的

题目解析我给我一个示例图:

这是从一个位置去另外三个位置去选择最小值,那从一个位置到达(i,j)位置,我们可以从哪里到达

这三个位置均可以到达(i,j)位置  

那么我们已经知道了从哪里到达(i,j)位置,我们就需要知道到达(i,j)位置前的位置的最小路径和,也就是这个位置的dp值,我们已知三个位置可以到达(i,j)位置,那么我们从中选一个最小的就需要在这三个里面作比较,最终再加上(i,j)位置的路径数大小,就是dp[i][j]。

状态转移方程:dp[i][j]=min( min( dp[i-1][j-1] , dp[i-1][j] ) , dp[i][j+1] ) + (i,j)位置的数

3、初始化

 我们创建dp表就是为了把他填满,我们初始化是为了防止在填表的过程中越界

怎么谈越界?

我们在填dp[0][0]时,我们会发现,到达该位置前的三个位置根本不存在

dp表初始化:

另外,不仅是(0,0)位置,第一行和第一列以及最后一列都存在类似的问题

所以我们在初始化时,要额外的增加一行两列

特殊位置初始化:

  在求最小问题时,我们在不能让那些为了防止越界而额外添加的位置,在数据上影响我们填表,所以我们要进行一些位置的初始化:

  一些数据初始化为INT_MAX,是因为防止其与其它原有数据比较时产生影响,我们设置成INT_MAX就可以忽略这个问题了

4、填表顺序

从左到右,从上到下依次填表

5、返回值

  这里返回值有点特殊,我们到达最后一行时,最小路径并不在最后一个位置,最小路径是取决于原表中最后一行数据大小,所以填完表我们需要对最后一行进行最小值的筛选

三、编写代码

class Solution {
public:int minFallingPathSum(vector<vector<int>>& matrix) {int m=matrix.size();//1、创建dp表vector<vector<int>> dp(m+1,vector<int>(m+2,INT_MAX));//2、初始化for(int i=0;i<=m+1;i++){dp[0][i]=0;}//3、填表for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){dp[i][j]=min(min(dp[i-1][j-1],dp[i-1][j]),dp[i-1][j+1])+matrix[i-1][j-1];}}//4、筛选最小值int ret=INT_MAX;for(int j=1;j<=m;j++){if(ret>dp[m][j]){ret=dp[m][j];}}//5、返回值return ret;}
};

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com