最大得分的路径数目
给你一个正方形字符数组 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
代码:
状态转移方程为:
f
[
(
x
,
y
)
]
=
m
a
x
(
f
[
(
x
+
1
,
y
)
]
,
f
[
(
x
,
y
+
1
)
]
,
f
[
(
x
+
1
,
y
+
1
)
]
)
+
b
o
a
r
d
[
(
x
,
y
)
]
f[(x,y)]=max(f[(x+1,y)],f[(x,y+1)],f[(x+1,y+1)])+board[(x,y)]
f[(x,y)]=max(f[(x+1,y)],f[(x,y+1)],f[(x+1,y+1)])+board[(x,y)]
/*
动态规划
定义
dp[i][j] 表示从起点到位置i,j的状态,包含刘昂部分,即 得分 和 路径数量 两部分
初始化
dp[n-1][n-1] = {0, 1}
其他均初始化为 {-1, 0}
计算
从右下角开始计算,即从大到小
考虑三种情况到x,y
x+1, y
x, y+1
x+1, y+1
结果
dp[0][0]的结果,记得要考虑是否可达的情况
*/
class Solution {
private:
int n;
int base = 1000000007;
// 合并的结果函数:需要考虑两种情况(1、找到更大的值,即直接更新结果;2、找到一样的值,则方案数量要累加)
// x,y表示目的地, sx,sy表示起始点
void reach(vector<vector<vector<int>>>& dp, int x, int y, int sx, int sy)
{
if (sx < n && sy < n && dp[sx][sy][0] >= 0)
{
if (dp[sx][sy][0] > dp[x][y][0])
{
dp[x][y] = dp[sx][sy];
}
else if (dp[sx][sy][0] == dp[x][y][0])
{
dp[x][y][1] += dp[sx][sy][1];
dp[x][y][1] %= base;
}
}
}
public:
vector<int> pathsWithMaxScore(vector<string>& board) {
n = board.size();
vector<vector<vector<int>>> dp(n, vector<vector<int>>(n, {-1, 0}));
dp[n-1][n-1] = {0, 1};
// 设置board为'0'减少后续判断
board[0][0] = '0';
for (int i = n-1; i >= 0; --i)
{
for (int j = n-1; j >= 0; --j)
{
if (i == n-1 && j == n-1)
{
continue;
}
else if (board[i][j] == 'X')
{
continue;
}
reach(dp, i, j, i+1, j);
reach(dp, i, j, i, j+1);
reach(dp, i, j, i+1, j+1);
if (dp[i][j][0] != -1)
{
dp[i][j][0] += board[i][j] - '0';
}
}
}
return dp[0][0][0] == -1 ? vector<int>(2,0) : dp[0][0];
}
};
//优化版
using PII = pair<int, int>;
class Solution {
private:
static constexpr int mod = (int)1e9 + 7;
public:
void update(vector<vector<PII>>& dp, int n, int x, int y, int u, int v) {
if (u >= n || v >= n || dp[u][v].first == -1) {
return;
}
if (dp[u][v].first > dp[x][y].first) {
dp[x][y] = dp[u][v];
}
else if (dp[u][v].first == dp[x][y].first) {
dp[x][y].second += dp[u][v].second;
if (dp[x][y].second >= mod) {
dp[x][y].second -= mod;
}
}
}
vector<int> pathsWithMaxScore(vector<string>& board) {
int n = board.size();
vector<vector<PII>> dp(n, vector<PII>(n, {-1, 0}));
dp[n - 1][n - 1] = {0, 1};
for (int i = n - 1; i >= 0; --i) {
for (int j = n - 1; j >= 0; --j) {
if (!(i == n - 1 && j == n - 1) && board[i][j] != 'X') {
update(dp, n, i, j, i + 1, j);
update(dp, n, i, j, i, j + 1);
update(dp, n, i, j, i + 1, j + 1);
if (dp[i][j].first != -1) {
dp[i][j].first += (board[i][j] == 'E' ? 0 : board[i][j] - '0');
}
}
}
}
return dp[0][0].first == -1 ? vector<int>{0, 0} : vector<int>{dp[0][0].first, dp[0][0].second};
}
};