图文解答之最短路径||

该文章介绍了一个使用动态规划算法解决的问题,即在一个包含障碍物的网格中,从左上角到右下角有多少条不同的最短路径。通过遍历网格并计算每个格点的可达路径数量,最终得到目标位置的路径总数。算法的时间复杂度为O(N^M),空间复杂度也为O(N^M),其中N和M分别为网格的行数和列数。

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

最短路径||
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。
说明:m 和 n 的值均不超过 100。
例子:
输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:

  1. 向右 -> 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右 -> 向右

解题思路:
如果格子上有障碍,那么我们不考虑包含这个格子的任何路径。我们从左至右、从上至下的遍历整个数组,那么在到达某个顶点之前我们就已经获得了到达前驱节点的方案数,这就变成了一个动态规划问题。我们只需要一个 Grid 数组来存储到达格点的方案数。

算法步骤:

  1. 状态:既每个格点到达的方案数,存在grid二维数组中,状态初始化:机器人只可以向下和向右移动,因此第一行的格子只能从左边的格子移动到,第一列的格子只能从上方的格子移动到。所以他们根据情况是1或者0.
  2. 决策:除了初始化的第一行和第一列,余下每个格点都是grid[i][j]=grid[i-1][j]+grid[i][j-1]
  3. 阶段:由于机器人只可以向下和向右移动,要求的grid[i][j]格,必先知道上边和左边一格的方案数,所有我们从左到右,从上到下计算。
    数据分析:
    Int grid[N][N]:保存每个格点方案数。
    图解过程:
    过程图解
    复杂度分析:
    时间复杂度:O(N^M)
    空间复杂度:O(N^M)
#include <stdio.h>
int uniquePathsWithObstacles(int obstacleGrid[][20], int obstacleGridSize, int obstacleGridColSize){
    if (obstacleGridSize == 0 || obstacleGridColSize == 0)
    {
        return 0;
    }
    int m = obstacleGridSize;
    int n = obstacleGridColSize;
    unsigned int dq[m][n];  // 用int的话,测试用例会超范围
    int i;
    int j;

    // 如果起始位置就是1,则直接返回0
    if (obstacleGrid[0][0] == 1)
    {
        return 0;
    }

    // 将初始位置置为1
    dq[0][0] = 1;
    // 处理第一列,遇到过障碍物之后,后面的都无法到达,因此都是0
    for (i = 1; i < m; i++) {
        if (obstacleGrid[i][0] == 1 || dq[i - 1][0] == 0) {
            dq[i][0] = 0;
        } else {
            dq[i][0] = 1;
        }
    }

    // 处理第一行,遇到过障碍物之后,后面的都无法到达,因此都是0
    for (j = 1; j < n; j++) {
        if (obstacleGrid[0][j] == 1 || dq[0][j - 1] == 0) {
            dq[0][j] = 0;
        } else {
            dq[0][j] = 1;
        }
    }

    for (i = 1; i < m; i++) {
        for (j = 1; j < n; j++) {
            if (obstacleGrid[i][j]) {  // 如果当前的是障碍物,则这个地方无法到达,因此这个位置置为0
                dq[i][j] = 0;
            } else {
                dq[i][j] = dq[i - 1][j] + dq[i][j - 1]; // 到达这个位置可以由上面和左边两条路径到达,是到达上面和左边位置的路径之和
            }
        }
    }
    return dq[m - 1][n - 1];  // 返回到达目的地的路径之和
}

int main(){
	int a[20][20]={};
	int n,m;
	printf("输入行数,列数\n");
	 scanf("%d %d",&m,&n);
	printf("输入表格\n");	 
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) scanf("%d",&a[i][j]); 
	printf("%d",uniquePathsWithObstacles(a, m, n));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值