最大得分的路径数目

268 阅读2分钟

前言

“这是我参与8月更文挑战的第28天,活动详情查看:[8月更文挑战]

  1. 1301. 最大得分的路径数目

1301. 最大得分的路径数目


给你一个正方形字符数组 board ,你从数组最右下方的字符 'S' 出发。

你的目标是到达数组最左上角的字符 'E' ,数组剩余的部分为数字字符 1, 2, ..., 9 或者障碍 'X'。在每一步移动中,你可以向上、向左或者左上方移动,可以移动的前提是到达的格子没有障碍。

一条路径的 「得分」 定义为:路径上所有数字的和。

请你返回一个列表,包含两个整数:第一个整数是 「得分」 的最大值,第二个整数是得到最大得分的方案数,请把结果对 10^9 + 7 取余

如果没有任何路径可以到达终点,请返回 [0, 0] 。

 

示例 1:

输入: board = ["E23","2X2","12S"]
输出: [7,1]

示例 2:

输入: board = ["E12","1X1","21S"]
输出: [4,2]

示例 3:

输入: board = ["E11","XXX","11S"]
输出: [0,0]

 

提示:

  • 2 <= board.length == board[i].length <= 100

思路分析:

因为可以向上、向左或者左上方移动,那么对于 位置(i,j) 可能是由 位置(i,j+1) || (i+1,j) || (i+1, j+1)移动过来的

定义 dp[i][j] 表示到达位置(i, j) 的最大得分, 根据状态的转移, 可以推导出状态转移方程

dp[i][j] = max(dp[i][j+1], dp[i+1][j], dp[i+1][j+1]) + board[i][j]

需要注意 障碍物 'X'

定义 fp[i][j] 表示到达位置(i,j) 获取最大得分的方案数

fp[i][j] += dp[x][y] == maxScore ? fp[x][y] : 0;

注意 需要 将fp 对  10^9 + 7 取余

AC 代码:

    public int[] pathsWithMaxScore(List<String> board) {
                if (board == null || board.size() == 0) {
            return null;
        }
        int mod = 1000000007;
        int m = board.size();
        int n = board.get(0).length();

        char[][] chs = new char[m][n];

        for (int i = 0; i < m; i++) {
            chs[i] = board.get(i).toCharArray();
        }

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

        // base case 最后一行
        fp[m - 1][n - 1] = 1;
        for (int j = n - 2; j >= 0; j--) {
            if (chs[m - 1][j] == 'X') {
                dp[m - 1][j] = 0;
                fp[m - 1][j] = 0;
                continue;
            }
            int value = chs[m - 1][j] == 'E' ? 0 : chs[m - 1][j] - '0';
            if (fp[m - 1][j + 1] == 0) {
                dp[m - 1][j] = 0;
                fp[m - 1][j] = 0;
            } else {
                dp[m - 1][j] = dp[m - 1][j + 1] + value;
                fp[m - 1][j] = 1;
            }

        }


         
        for (int i = m - 2; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                if (chs[i][j] == 'X') {
                    dp[i][j] = 0;
                    fp[i][j] = 0;
                    continue;
                }
                int value = chs[i][j] == 'E' ? 0 : chs[i][j] - '0';
                int right = j + 1 < n && fp[i][j + 1] != 0 ? dp[i][j + 1] : -1;
                int bottom = fp[i + 1][j] != 0 ? dp[i + 1][j] : -1;
                int br = j + 1 < n && fp[i + 1][j + 1] != 0 ? dp[i + 1][j + 1] : -1;

                int select = Math.max(Math.max(right, bottom), br);
                if (select == -1) {
                    dp[i][j] = 0;
                    fp[i][j] = 0;
                } else {
                    dp[i][j] = select + value;
                    fp[i][j] = 0;
                    if (right == select) {
                        fp[i][j] += fp[i][j + 1];
                    }

                    if (bottom == select) {
                        fp[i][j] +=fp[i + 1][j];
                    }

                    if (br == select) {
                        fp[i][j] +=fp[i + 1][j + 1];
                    }
                }
                fp[i][j] %=mod;
            }
        }
        
        return new int[]{dp[0][0], fp[0][0]};
    }