每日一道leetcode(2026.04.30):网格中得分最大的路径

9 阅读3分钟

1. 题目

给你一个 m x n 的网格 grid,其中每个单元格包含以下值之一:0、1 或 2。另给你一个整数 k。

你从左上角 (0, 0) 出发,目标是到达右下角 (m - 1, n - 1),只能向 右 或 下 移动。

每个单元格根据其值对路径有以下贡献:

值为 0 的单元格:分数增加 0,花费 0。 值为 1 的单元格:分数增加 1,花费 1。 值为 2 的单元格:分数增加 2,花费 1。 返回在总花费不超过 k 的情况下可以获得的 最大分数 ,如果不存在有效路径,则返回 -1。

注意: 如果到达最后一个单元格时总花费超过 k,则该路径无效。

示例 1:

输入: grid = [[0, 1],[2, 0]], k = 1

输出: 2

解释:

最佳路径为:

在这里插入图片描述

示例 2:

输入: grid = [[0, 1],[1, 2]], k = 1

输出: -1

解释:

不存在在总花费不超过 k 的情况下到达单元格 (1, 1) 的路径,因此答案是 -1。

提示:

1 <= m, n <= 200 0 <= k <= 10e3 ​​​​​​​grid[0][0] == 0 0 <= grid[i][j] <= 2

2. 分析

这道题很容易想到使用bfs的解题思路,过程也很简单,直接递归去向右和向下移动,直到遇到边界或者是目标单元格。

    public int maxPathScore(int[][] grid, int k) {
        return dfs(grid, 0, 0, 0, k);
    }

    public static int dfs(int[][] grid, int i, int j, int score, int k) {
        if (i >= grid.length || j >= grid[0].length||k<0) {
            return -1;
        }
        score += grid[i][j];
        k -= grid[i][j] == 0 ? 0 : 1;
        if (i == grid.length - 1 && j == grid[0].length - 1 && k >= 0) {
            return score;
        }
        // 向下&向右
        return Math.max(dfs(grid, i + 1, j, score, k), dfs(grid, i, j + 1, score, k));
    }

由于类似于穷举,递归深度和运算量比较大,直接就超时了,我也没有继续验证这个代码是否完全正确,转而采用dp动态规划的思路解答。

首先能确认的是这是一个三维的动态方程,一个单元格的最大分数与单元格所在的行,列以及给定的变量k有关,dp[i][j][k]则与dp[i-1][j][k]和dp[i][j-1][k]强相关,可以从dp[0][0][k]开始遍历,分别求出各个单元格的最大分数。

3. 代码实现

    public int maxPathScore(int[][] grid, int k) {
        int row = grid.length;
        int col = grid[0].length;
        int[][][] dp = new int[row][col][k + 1];
        // 初始化值为-1
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                Arrays.fill(dp[i][j], -1);
            }
        }
        dp[0][0][k] = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                for (int kk = 0; kk <= k; kk++) {
                    if (dp[i][j][kk] == -1) {
                        continue;
                    }
                    // 向下
                    if (i + 1 < row) {
                        int val = grid[i + 1][j];
                        if (val == 0) {
                            dp[i + 1][j][kk] = Math.max(dp[i + 1][j][kk], dp[i][j][kk] + val);
                        } else if (kk >= 1) {
                            dp[i + 1][j][kk - 1] = Math.max(dp[i + 1][j][kk - 1], dp[i][j][kk] + val);
                        }
                    }
                    // 向右
                    if (j + 1 < col) {
                        int val = grid[i][j + 1];
                        if (val == 0) {
                            dp[i][j + 1][kk] = Math.max(dp[i][j + 1][kk], dp[i][j][kk] + val);
                        } else if (kk >= 1) {
                            dp[i][j + 1][kk - 1] = Math.max(dp[i][j + 1][kk - 1], dp[i][j][kk] + val);
                        }
                    }
                }
            }
        }
        int max = -1;
        for (int i = 0; i < dp[row - 1][col - 1].length; i++) {
            max = Math.max(max, dp[row - 1][col - 1][i]);
        }
        return max;
    }

在这里插入图片描述