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

Posted 一个正直的男孩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[动态规划与回溯算法] 路径问题相关的知识,希望对你有一定的参考价值。

第一层 三角矩阵

题目描述:

大白话:计算顶部到底步的路径,路径值相加求这个三角形的路径和中值最小,且每一步看一移动到当前位置的下一行,或下一行下一个 如 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];
    


唠唠家常

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

以上是关于[动态规划与回溯算法] 路径问题的主要内容,如果未能解决你的问题,请参考以下文章

[动态规划与回溯算法] 01背包

五类常见算法小记 (递归与分治,动态规划,贪心,回溯,分支界限法)

[动态规划与回溯算法]斐波那契数列与变形

[动态规划与回溯算法]斐波那契数列与变形

[动态规划与回溯算法] 01背包

动态规划回溯搜索分治算法分支限界算法