不同的路径Ⅱ

给定一个网格,0代表可以通过,1代表有障碍物,不能通过,求出有多少路径。

思路: 这是之前路径问题的升级版,我们首先要判断一下当前的网格是否有障碍,如果有障碍的话就将当前的dp记为0,因为不可能到达这里。然后将开始的位置00 记为 1,如果在第一行或者是第一列就只需要其前面或者上面的信息,否则是可以在上边或者左边两个地方过来的。

public class Solution {
    /**
     * @param obstacleGrid: A list of lists of integers
     * @return: An integer
     */
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        // write your code here
        int row = obstacleGrid.length;
        int col = obstacleGrid[0].length;
        int[][] dp = new int[row][col];
        int i, j;
        for(i = 0; i < row; i++){
            for(j = 0; j < col; j++){
                if(obstacleGrid[i][j] == 1){
                    dp[i][j] = 0;
                    continue;
                }
                if(i == 0 && j == 0){
                    dp[0][0] = 1;
                    continue;
                }
                if(i == 0){
                    dp[i][j] = dp[i][j - 1];
                    continue;
                }
                if(j == 0){
                    dp[i][j] = dp[i - 1][j];
                    continue;
                }
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[row - 1][col - 1];
    }
}
<think>好的,我现在需要帮助用户解决关于C++实现最小路径和问题的动态规划算法。用户明确提到了动态规划,所以我要先回顾一下动态规划的基本思路,尤其是路径问题中的应用。 首先,最小路径和问题通常是指在一个二维网格中,从左上角到右下角寻找一条路径,使得路径上的数值之和最小。每次只能向右或向下移动。这个问题和之前的不同路径问题类似,但这里每个格子有权重,需要求最小和,而不是路径数量。 接下来,我要确定动态规划的状态定义。通常,dp[i][j]表示从起点(0,0)(i,j)的最小路径和。状态转移方程应该是从上方或左方的格子转移过来,选择较小的那个加上当前格子的值。即dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])。不过需要注意边界条件,比如第一行和第一列,因为它们只能从一个方向来。 然后,初始化部分需要考虑起点dp[0][0] = grid[0][0]。对于第一行的每个元素,只能从左边来,所以dp[0][j] = dp[0][j-1] + grid[0][j]。同理,第一列每个元素只能从上方来,dp[i][0] = dp[i-1][0] + grid[i][0]。 接下来,考虑如何优化空间复杂度。因为每次计算只需要左边和上边的值,可能可以只用一维数组或者直接修改原数组(如果允许的话)。不过用户可能需要标准的动态规划实现,所以先用二维数组来说明。 然后,我需要参考用户提供的引用内容。引用[2]中提到了不同路径问题的动态规划代码,初始化时使用了dp[0][1] = 1,然后循环填充。但最小路径和问题需要处理权重,所以初始化部分可能需要调整。比如,如果使用类似的二维数组,初始条件应该是dp[0][0] = grid[0][0],然后处理第一行和第一列。 再想,用户可能需要具体的代码示例,所以需要用C++实现。需要处理输入为一个二维数组grid,输出最小路径和。同时,考虑网格中有负数的情况,但路径和仍然要最小,所以不能使用贪心,必须动态规划。 现在,可能的边界情况包括网格为空、只有一行或一列,或者网格中有障碍物(但用户的问题中可能没有障碍物,因为引用[2]中的不同路径Ⅱ是另一个问题)。但用户的问题是最小路径和,所以暂时假设网格中没有障碍物,所有格子都是可走的。 然后,编写代码的大致步骤: 1. 获取网格的行数m和列数n。 2. 创建dp二维数组,大小和网格相同。 3. 初始化dp[0][0]为grid[0][0]。 4. 初始化第一行和第一列。 5. 遍历其他格子,填充dp数组。 6. 返回dp[m-1][n-1]。 或者,可以优化空间,使用一维数组,因为每次计算当前行时只需要上一行的数据和当前行左边的数据。但为了清晰,先给出二维数组的实现。 测试案例,比如: 输入:[[1,3,1],[1,5,1],[4,2,1]],输出应该是7,路径1→3→1→1→1。 现在,检查用户提供的引用中的代码是否有参考价值。引用[2]中的不同路径问题代码使用了一个dp数组,初始化dp[0][1]=1,然后填充。这可能是因为他们使用了1-based索引,但最小路径和问题可能更适合0-based。需要注意索引的处理。 另外,用户的问题中的网格可能从左上角到右下角,每个步骤只能右或下,所以动态规划的顺序应该是逐行逐列填充。 最后,确保代码正确处理所有情况,没有越界,并且在C++中正确处理二维vector的初始化。</think>### C++实现最小路径和的动态规划算法 #### 问题描述 给定一个包含非负整数的$m \times n$网格,从左上角到右下角寻找一条路径,使得路径上的数字总和最小。每次只能向右或向下移动。 #### 算法思路 1. **状态定义** 定义$dp[i][j]$表示从起点$(0,0)$到点$(i,j)$的最小路径和。 2. **状态转移方程** - 第一行只能从左向右累加:$dp[0][j] = dp[0][j-1] + grid[0][j]$ - 第一列只能从上到下累加:$dp[i][0] = dp[i-1][0] + grid[i][0]$ - 其他位置:$dp[i][j] = \min(dp[i-1][j], dp[i][j-1]) + grid[i][j]$ 3. **空间优化** 可以直接在原数组上修改,避免额外空间占用。 #### C++代码实现 ```cpp #include <vector> #include <algorithm> // for std::min int minPathSum(std::vector<std::vector<int>>& grid) { int m = grid.size(); int n = grid[0].size(); // 初始化第一列 for (int i = 1; i < m; ++i) { grid[i][0] += grid[i-1][0]; } // 初始化第一行 for (int j = 1; j < n; ++j) { grid[0][j] += grid[0][j-1]; } // 填充其他位置 for (int i = 1; i < m; ++i) { for (int j = 1; j < n; ++j) { grid[i][j] += std::min(grid[i-1][j], grid[i][j-1]); } } return grid[m-1][n-1]; } ``` #### 代码说明 1. **初始化第一行和第一列**:直接累加前一个元素的值,形成初始路径和。 2. **动态填充其他位置**:通过比较上方和左方的最小值,逐步更新最小路径和。 3. **时间复杂度**:$O(m \times n)$,空间复杂度:$O(1)$(直接修改原数组)。 #### 示例验证 输入网格: $$ \begin{bmatrix} 1 & 3 & 1 \\ 1 & 5 & 1 \\ 4 & 2 & 1 \end{bmatrix} $$ 输出最小路径和为$7$,路径为:$1 \rightarrow 3 \rightarrow 1 \rightarrow 1 \rightarrow 1$[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值