08-24 不同路径问题总结(两点之间有多少种走法)

08-24 不同路径

1、起点为原点(0,0)

题目

我们可以把棋盘的左下角看做二维坐标的原点(0,0),把棋盘的右上角看做二维坐标(M,N)(坐标系的单位长度为小方格的变长)

思路

用f(i,j)表示移动到坐标f(i,j)的走法总数,其中0=<i,j<=n,设f(m,n)代表从坐标(0,0)到坐标(m,n)的移动方法,则
f(m,n)=f(m-1,n)+f(m,n-1).

于是状态f(i,j)的状态转移方程为:

f(i,j)=f(i-1,j)+f(i,j-1) if i,j>0

f(i,j)=f(i,j-1) if i=0

f(i,j)=f(i-1,j) if j=0

初始情况就为:f(0,0)=0, f(0,1)=1, f(1,0)=1,这个问题可以在时间O(n^2) 内求解,非递归解.

代码

/*非递归解法*/
int processNew(int m,int n){

	vector<vector<int>> Q(m+1,vector<int> (n+1,0));
	
    //初始化
    for(int j=1; j<=n; ++j)
        Q[0][j]=1;
    for(int i=1; i<=m; ++i)
        Q[i][0]=1;
    
    //迭代计算
    for(int i=1; i<=m; ++i){
        for(int j=1; j<=n; ++j){
            Q[i][j]=Q[i-1][j]+Q[i][j-1];
        }
    }
    int res=Q[m][n];
    return res;
}


/递归解法

int process(int m, int n) {
    /*if (m == 0 && n == 0)    我觉得这部分不要
        return 0;*/                    
    if (m==0 || n==0)
        return 1;
    return process(m, n - 1) + process(m - 1, n);



2、起点不在原点

题目

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

问总共有多少条不同的路径?
在这里插入图片描述

例如,上图是一个7 x 3 的网格。有多少可能的路径?

说明:m 和 n 的值均不超过 100。

代码

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m+1,vector<int> (n+1,0));
        dp[1][1]=1;     //可以初始化dp[1][0]=1或者dp[0][1]=1;更方便
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            {
                if(i==1 && j==1)
                    continue;
                dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        return dp[m][n];
    }
};
/*
class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m+1,vector<int> (n+1,0));
        dp[1][0]=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];
    }
};
*/

3、LeetCode 63 不同路径II

题目

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
在这里插入图片描述

网格中的障碍物和空位置分别用 1 和 0 来表示。

说明:m 和 n 的值均不超过 100。

示例 1:

输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2

代码

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m=obstacleGrid.size();
        int n=obstacleGrid[0].size();
        
        vector<vector<long long>> dp(m+1,vector<long long > (n+1,0));
        dp[1][0]=1;      //不用在起点开始,这里是重点
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            {
                if(obstacleGrid[i-1][j-1]==1)
                    continue;
                dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        return dp[m][n];
    }
};

4、不经过某一点

题目

在如下86的矩阵中,请计算从A移动到B一共有__*种走法。要求每次只能向上或向右移动一格,并且不能经过P。
在这里插入图片描述

思路

86的矩阵,从左下角A到右上角B,一共需要走12步,其中5步向上,7步向右,因此总的走法一共有C(12,5)=792种,但题目规定不能经过P,因此需要减去经过P点的走法。
经过P的路径分为两部分,从A到P,从P到B。
同理,从A到P的走法:C(6,2)=15;
同理,从P到B的走法:C(6,3)=20;
因此从A到B经过P点的走法有15
20=300种,
所以从A到B不经过P点的走法有792-300=492种。

这题其实可以用程序算出来
简单的动态规划

dp[i][j] = dp[i][j-1] + dp[i-1][j];

代码**

 #include <bits/stdc++>
  using namespace std;
  int main()
  {
   	 int dp[7][9] = {0};
 	 dp[1][0]=1;
      
   	 for(int i = 1; i <= 6; i++)
     	for(int j = 1; j <= 8; j++)      
         	dp[i][j] = dp[i-1][j] + dp[i][j-1];
     
     cout<<dp[6][8] - dp2[4][4] * dp[3][5]<<endl;  //输出492正确
 
     return 0;
  }

此类题目还有:A点到B点的最短路径,那么只需要比较dp[i-1][j] 和 dp[i][j-1]哪个小了

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值