# 动态规划解决最小路径和问题:从错误中学习正确解法

# 动态规划解决最小路径和问题:从错误中学习正确解法_第1张图片

 

## 题目描述

给定一个包含非负整数的 \( m \times n \) 网格 `grid`,找出一条从左上角到右下角的路径,使得路径上的数字总和最小。每次只能向下或向右移动一步。

 

## 解题思路

动态规划是解决此类问题的经典方法。核心思路是:

1. **定义状态**:`dp[i][j]` 表示从左上角到 `(i,j)` 位置的最小路径和。

2. **初始化**:起点的值 `dp[0][0] = grid[0][0]`。第一行和第一列的值只能通过单一方向累加。

3. **状态转移**:对于其他位置 `(i,j)`,路径和为左边或上边的最小值加上当前值:  

   `dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]`。

4. **结果**:返回 `dp[m-1][n-1]`。

 

## 原代码问题分析

以下是用户提供的错误代码中的关键问题:

 

### 1. 未正确初始化起点

```java

int[][] dp = new int[m][n];

// 缺少 dp[0][0] = nums[0][0];

```

起点必须初始化为网格的第一个值,否则后续计算全部错误。

 

### 2. 未累加当前网格的值

```java

// 错误代码示例:未加当前值

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

// 正确应为:dp[i][0] = dp[i-1][0] + nums[i][0];

```

第一行和第一列的初始化必须包含当前网格的值,否则路径和会遗漏当前格。

 

### 3. 数组越界问题

```java

// 错误示例:循环条件错误

for (int j = 1; j < nums[m].length; j++) {

```

`nums[m]` 会导致越界(数组索引最大为 `m-1`)。应使用 `n`(列数)作为循环条件。

 

### 4. 循环变量递增错误

```java

// 内层循环变量错误

for (int j = 1; j < n; i++) { 

```

`i++` 会导致 `j` 不变化,引发死循环或越界。应改为 `j++`。

 

---

 

## 修正后的代码

```java

import java.util.Scanner;

 

public class Main {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int m = sc.nextInt();

        int n = sc.nextInt();

        int[][] grid = new int[m][n];

        for (int i = 0; i < m; i++) {

            for (int j = 0; j < n; j++) {

                grid[i][j] = sc.nextInt();

            }

        }

        System.out.println(minPathSum(grid));

    }

 

    public static int minPathSum(int[][] grid) {

        int m = grid.length;

        int n = grid[0].length;

        int[][] dp = new int[m][n];

        dp[0][0] = grid[0][0]; // 初始化起点

 

        // 初始化第一列

        for (int i = 1; i < m; i++) {

            dp[i][0] = dp[i-1][0] + grid[i][0];

        }

 

        // 初始化第一行

        for (int j = 1; j < n; j++) {

            dp[0][j] = dp[0][j-1] + grid[0][j];

        }

 

        // 填充其他位置

        for (int i = 1; i < m; i++) {

            for (int j = 1; j < n; j++) {

                dp[i][j] = Math.min(dp[i-1][j], dp[i][j-1]) + grid[i][j];

            }

        }

 

        return dp[m-1][n-1];

    }

}

```

 

---

 

## 易错点总结

1. **起点未初始化**:必须显式设置 `dp[0][0] = grid[0][0]`。

2. **路径和未累加当前值**:第一行和第一列的每个位置都需要加上当前网格的值。

3. **数组越界**:确保循环条件正确,尤其是对二维数组的索引。

4. **循环变量错误**:注意 `for` 循环的变量名和递增逻辑。

5. **边界条件处理**:当 `m=0` 或 `n=0` 时需单独处理(题目中网格为非负整数,但实际可能需要返回0)。

 

通过修正这些问题,代码可以正确计算最小路径和。

你可能感兴趣的:(java,动态规划,leetcode,算法,动态规划)