[动态规划与回溯算法] 路径问题

这篇博客探讨了两种路径优化问题。第一部分是计算三角矩阵的最小路径和,使用动态规划自底向上求解,通过状态转移方程找到最小路径。第二部分介绍了机器人到达终点的最短路径,同样利用动态规划,根据机器人只能向下或向右移动的限制,求解路径数量。博客强调了逆序思考在解决此类问题时的简化作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一层 三角矩阵

题目描述:
在这里插入图片描述

大白话:计算顶部到底步的路径,路径值相加求这个三角形的路径和中值最小,且每一步看一移动到当前位置的下一行,或下一行下一个 如 index:(i,j) --> (i-1,j) 或(i-1,j-1)


思路1:

“三”

状态抽象:

由题可以知道我们需要求最小路径和,也就是最后最后一个位置的路径和,那么我们就可以先求第i个位置 如图所示:
在这里插入图片描述
那么我们要知道到i节点的路径和,就和求最后位置一样,且我们还需要保存第i个状态的结果,因为 i 这个结果是 i+1 个位置需要的


状态的转移方程:

由上述分析可以得出(i,j)这个位置可以访问的 (i-1,j) (i-1,j-1),这个其实就是他的状态转移方程,且是他们中的最小值

特殊状况:

在这里插入图片描述

当节点为当前行第一个和最后一个的时候 , 那么可以访问他的路径只有路径只有 1个

  1. 60 index=[2,0]–>[1,0] (i-1,j)
    –>[1,-1]明显下标没有(i-1,j-1)
  2. 70 index=[2,3]–>[1,3]–>明显上一路径也没有 (i-1,j)
    –>[1,2] 明显下标没有(i-1,j-1)

状态初始化

状态初始化,其实现在来看已经显而易见了,其实就是(0,0) 这个位置,因为这个位置的路径和就是他本身


”一“
显然动归这一类题是需要保存之前求出来的解,一般是由数组来储存,由题可以看出要用一个二维数组去存储解

代码:


    int minimumTotal(vector<vector<int> > &triangle)
    {
        //写法自上到下
        //1.走到(x,y)这个位置只有俩种情况--> 1. (x-1,y) 2.(2-1,y-1)
        //2.特殊情况,在左右俩边的节点的路径是唯一确定的
        
        
        //初始状态
        //triangle[0][0]
        
        //状态的定义与状态的转移方程
        int i=0;
        //状态定义
        for(i =1;i<triangle.size();i++)
        {
            for(int j=0;j<triangle[i].size();j++)
            {
                 //转移方程
                //特殊情况
                if(j==0)
                {
                    triangle[i][j]+=triangle[i-1][j];
                }
                else if(j==i)
                {
                     triangle[i][j]+=triangle[i-1][j-1];
                }
                
                else
                {
                    triangle[i][j]+=min(triangle[i-1][j],triangle[i-1][j-1]);//找最小的值
                }
            }
        }
        
        
        
        //寻找最小值
        for(int j=1;j<triangle[i-1].size();j++)
        {
                   if(triangle[i-1][0]>triangle[i-1][j])
                   {
                       triangle[i-1][0]=triangle[i-1][j];//把最小值放到最后一行第一个位置
                   }
        }
          
        return triangle[i-1][0];//返回结果
    }

优化:

上面你会发现好麻烦呀,最烦的是那么多限制条件,最后还要遍历找最小的路径很就不太人性,没事下面我们思维来拐个弯,我们可不可以把最后一个节点当做初始状态,从下往上找那么我们就不需要找最小路径了

在这里插入图片描述

初始状态:

我们直接把最后一行看作初始状态

在这里插入图片描述

转移方程

当 index:(i,j) 他可以访问 (i+1,j) 或 (i+1,j+1) ,这就是他的转移方程,依旧是俩者中的最小值

在这里插入图片描述

代码:

   int minimumTotal(vector<vector<int> > &triangle)
    {
    
        //初始状态
        //整个triangle[最后一行][0]~~triangle[最后一行][最后一个]
        
        
        //定义状态和转移方程
        for(int i =triangle.size()-2;i>=0;--i) //i为倒数第二行 
        {
            for(int j =0;j<triangle[i].size();j++)
            {
                triangle[i][j]+=min(triangle[i+1][j],triangle[i+1][j+1]);//俩者中最小的那个
            }
        }
           return  triangle[0][0];
    }




第二层 机器人到终点的路径

题目描述:

在这里插入图片描述


思路:

由题可以得知🤖️只可以向下或者向右移动,这个很关键,那么我们可以知道要求最终路径和(设最终路径为 x,y) 其实就是 上一行当前节点的位置当前行的前一个位置的和, (x-1,y)+(x,y-1)


状态的抽象

那么我们可以先求第i个状态的路径,然后再去推到最终路径

状态的转移方程

其实在上述的分析你已经可以看出他的转移方程是啥了(x-1,y)+(x,y-1)

状态初始化

知道🤖️只可以向右或者向下走,那么(0,j) 和(i,0)都为1,黄色区域为1

在这里插入图片描述

因为第一行和第一列的状态都是已知的所以我们只需要从(1,1)这个状态开始求路径个数


代码:

 int uniquePaths(int m, int n)
    {

        //一
        //保存i状态的解的容器
        vector<vector<int>>explain;
        vector<int> d1;
        //初始状态
        //第一行与第一列都为1
        d1.resize(m,1);
        explain.resize(n,d1);


        //状态定义与转移方程
        //转移方程:(i,j) = (i-1,j) 或(i,j-1)
        for(int i =1;i<n;i++)
        {
            for(int j =1;j<m;j++)
            {
                explain[i][j]=explain[i-1][j]+explain[i][j-1];
            }
        }

        //返回结果
        return explain[n-1][m-1];
    }


唠唠家常

我发现类似第一题这样如果 从前往后,自上而下 或 正序写如果很麻烦那么逆序一般情况来说都比较简单,只要脑子转个弯好多问题都变得简单了

在这里插入图片描述

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值