前言
“这是我参与8月更文挑战的第28天,活动详情查看:[8月更文挑战]
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]};
}