[LeetCode] 1301. Number of Paths with Max Score 最大得分的路徑數目
You are given a square board
of characters. You can move on the board starting at the bottom right square marked with the character 'S'
.
You need to reach the top left square marked with the character 'E'
. The rest of the squares are labeled either with a numeric character 1, 2, ..., 9
or with an obstacle 'X'
Return a list of two integers: the first integer is the maximum sum of numeric characters you can collect, and the second is the number of such paths that you can take to get that maximum sum, taken modulo 10^9 + 7
In case there is no path, return [0, 0]
.
Example 1:
Input: board = ["E23","2X2","12S"]
Output: [7,1]
Example 2:
Input: board = ["E12","1X1","21S"]
Output: [4,2]
Example 3:
Input: board = ["E11","XXX","11S"]
Output: [0,0]
Constraints:
2 <= board.length == board[i].length <= 100
這道題給了一個二維陣列 board,說是起始點在陣列的右下角,用字元S表示,終點在左上方,用E表示,其他位置可能是數字或者是字元X,其中X表示障礙物,不能通過,而數字表示可以收集的分數,現在讓從起點走到終點,並返回兩個數字,一個是可以得到的最大分數,另一個是得到該分數的不同路徑的個數(需要對一個超大數取餘)。博主現在只要一看到說是結果要對一個超大數取餘,下意識就會想到是要用動態規劃 Dynamic Programming 來做。這道題的每個狀態有兩個資訊,一個是當前的最大得分,另一個是獲得該得分的不同路徑數,為了簡單起見,分別用兩個陣列 score 和 path 來表示,其中 score[i][j] 表示從 (n-1, n-1) 到 (i, j) 位置可獲得的最大分數,path[i][j] 獲得 score[i][j] 分數的不同路徑個數,將 path[n-1][n-1] 初始化為1。
這道題的本質還是算迷宮遍歷的題目,只不過不再是上下左右這四個方向,而是左,上,和左上這三個方向。但整體的思路還是 BFS 遍歷的那一套,遍歷的方向是從右下角開始,一層一層的向上遍歷,最終到達左上角。對於每個遍歷到的位置 (i, j),判斷若 path[i][j] 為0,表示沒有路徑能到達這個位置,直接跳過。否則就遍歷其左邊,上邊,和左上邊的位置,若越界了,或者是障礙物X,則直接跳過。否則將該位置的分數取出(注意判斷下是否為結束位置E),加上原來位置的分數 score[i][j],得到總分數 sum。比較一下 sum 和 score[x][y] 的值,若 sum 大,則將 sum 賦值給 score[x][y],並且將 path[i][j] 賦值給 path[x][y],這不難理解吧,因為小的分數的路徑數就沒用了,所以可以直接覆蓋掉。而若 sum 和 score[x][y] 相等的話,則表示有了不同的路徑,需要將 path[i][j] 加到 path[x][y] 中,記得要對超大數取餘,這樣更新完成了之後,最後的結果就分別存在 score[0][0] 和 path[0][0] 之中了,參見程式碼如下:
class Solution {
public:
vector<int> pathsWithMaxScore(vector<string>& board) {
int n = board.size(), M = 1e9 + 7;
vector<vector<int>> score(n, vector<int>(n)), path = score;
vector<vector<int>> dirs{{0, -1}, {-1, 0}, {-1, -1}};
path[n - 1][n - 1] = 1;
for (int i = n - 1; i >= 0; --i) {
for (int j = n - 1; j >= 0; --j) {
if (path[i][j] == 0) continue;
for (auto dir : dirs) {
int x = i + dir[0], y = j + dir[1];
if (x < 0 || y < 0 || board[x][y] == 'X') continue;
int sum = score[i][j];
if (board[x][y] != 'E') sum += board[x][y] - '0';
if (sum > score[x][y]) {
score[x][y] = sum;
path[x][y] = path[i][j];
} else if (sum == score[x][y]) {
path[x][y] = (path[x][y] + path[i][j]) % M;
}
}
}
}
return {score[0][0], path[0][0]};
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1301
參考資料:
https://leetcode.com/problems/number-of-paths-with-max-score/
https://leetcode.com/problems/number-of-paths-with-max-score/discuss/463539/C%2B%2B-DP