[动态规划与回溯算法] 路径问题
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个
- 60 index=[2,0]–>[1,0] (i-1,j)
–>[1,-1]明显下标没有(i-1,j-1)- 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];
唠唠家常
我发现类似第一题这样如果 从前往后,自上而下 或 正序写如果很麻烦那么逆序一般情况来说都比较简单,只要脑子转个弯好多问题都变得简单了
以上是关于[动态规划与回溯算法] 路径问题的主要内容,如果未能解决你的问题,请参考以下文章