题目链接
题目描述
实现代码
dfs递归遍历实现代码:(超时)
class Solution {int max = 0;int count = 0;public int[] pathsWithMaxScore(List<String> board) {int n = board.size();int[][] arr = new int[n][n];for (int i = 0; i < n; i++) {String str = board.get(i);for (int j = 0; j < n; j++) {char c = str.charAt(j);if(c >= '0' && c <= '9') {arr[i][j] = c - '0';} else if(c == 'S'){arr[i][j] = 0;} else {arr[i][j] = Integer.MAX_VALUE;}}}dfs(arr, n, n - 1, n - 1, 0);return new int[]{max, count};}private void dfs(int[][] arr, int n, int curX, int curY, int curMax) {if (curX < 0 || curX > n - 1) {return;}if (curY < 0 || curY > n - 1) {return;}if (curX == 0 && curY == 0) {if (curMax == max) {count++;} else if (curMax > max) {max = curMax;count = 1;}return;}if(arr[curX][curY] == Integer.MAX_VALUE) {return;}curMax += arr[curX][curY];dfs(arr, n, curX-1, curY, curMax);dfs(arr, n, curX, curY-1, curMax);dfs(arr, n, curX-1, curY-1, curMax);}}
动态规划思想:
class Solution {int INF = Integer.MIN_VALUE;int mod = (int)1e9+7;int n;public int[] pathsWithMaxScore(List<String> board) {n = board.size();// 将 board 转存成二维数组char[][] cs = new char[n][n];for (int i = 0; i < n; i++) {cs[i] = board.get(i).toCharArray();}// f(i) 代表从右下角到位置 i 的最大得分int[] f = new int[n * n];// f(i) 代表从右下角到位置 i 并取到最大得分的方案数量int[] g = new int[n * n];for (int i = n - 1; i >= 0; i--) {for (int j = n - 1; j >= 0; j--) {int idx = getIdx(i, j);// 一个初始化的状态,如果是在最后一格(起点):// g[idx] = 1 : 代表到达起点的路径只有一条,这样我们就有了一个「有效值」可以滚动下去// f[idx] = 0 : 代表在起点得分为 0if (i == n - 1 && j == n - 1) {g[idx] = 1;continue;}// 如果该位置是「障碍点」,那么对应状态为:// g[idx] = 0 : 「障碍点」不可访问,路径为 0// f[idx] = INF : 「障碍点」不可访问,得分为无效值if (cs[i][j] == 'X') {f[idx] = INF;continue;}// 如果是第一个格子(终点),这时候位置得分为 0int val = (i == 0 && j == 0) ? 0 : cs[i][j] - '0';// u 代表当前位置的「最大得分」;t 代表取得最大得分的「方案数」int u = INF, t = 0;// 如果「下方格子」合法,尝试从「下方格子」进行转移if (i + 1 < n) {int cur = f[getIdx(i + 1, j)] + val;int cnt = g[getIdx(i + 1, j)];int[] res = update(cur, cnt, u, t);u = res[0]; t = res[1];}// 如果「右边格子」合法,尝试从「右边格子」进行转移if (j + 1 < n) {int cur = f[getIdx(i, j + 1)] + val;int cnt = g[getIdx(i, j + 1)];int[] res = update(cur, cnt, u, t);u = res[0]; t = res[1];}// 如果「右下角格子」合法,尝试从「右下角格子」进行转移if (i + 1 < n && j + 1 < n) {int cur = f[getIdx(i + 1, j + 1)] + val;int cnt = g[getIdx(i + 1, j + 1)];int[] res = update(cur, cnt, u, t);u = res[0]; t = res[1];}// 更新 dp 值f[idx] = u < 0 ? INF : u;g[idx] = t;}}// 构造答案int[] ans = new int[2];// 如果终点不可达(动规值为 INF)时,写入 0ans[0] = f[getIdx(0, 0)] == INF ? 0 : f[getIdx(0, 0)];// 如果终点不可达(动规值为 INF)时,写入 0ans[1] = f[getIdx(0, 0)] == INF ? 0 : g[getIdx(0, 0)];return ans;}// 更新 dp 值int[] update(int cur, int cnt, int u, int t) {// 起始答案为 [u, t] : u 为「最大得分」,t 为最大得分的「方案数」int[] ans = new int[]{u, t};// 如果当前值大于 u,更新「最大得分」和「方案数」if (cur > u) {ans[0] = cur;ans[1] = cnt;// 如果当前值等于 u,增加「方案数」} else if (cur == u && cur != INF) {ans[1] += cnt;}ans[1] %= mod;return ans;}// 二维坐标 (x,y) 与 idx 的相互转换int getIdx(int x, int y) {return x * n + y;}int[] parseIdx(int idx) {return new int[]{idx / n, idx % n};}}
在动态规划的基础上对复杂度进行优化(使用结构体):
class Solution {final int MOD = 1000000007;public int[] pathsWithMaxScore(List<String> board) {int n = board.size();//将给的字符表转化成字符矩阵char[][] map = new char[n][n];for(int i = 0; i < n; i++){map[i] = board.get(i).toCharArray();}//初始化边界条件都要为0Info[][] f = new Info[2][n+1];for(int i = 0; i <= n; i++){f[0][i] = new Info(0,0);f[1][i] = new Info(0,0);}int last = 0,now = 1;for(int i = n-1;i >= 0; i--){last = now;now = 1 - now;for(int j = n-1; j >= 0; j--){if(i == n-1 && j == n-1) {//将起始分数设为1是为区分围墙全面堵死情况// 因为在右,右下,下三块均为0,说明堵死,就是现在这一块有分数也不能加//但是起始点三块都0,必须区分,起始要加,其他情况不加f[now][j] = new Info(1,1);}elseif(i == 0 && j == 0){f[now][j] = MaxInfo(f[last][j],f[last][j+1],f[now][j+1]);}elseif(map[i][j] == 'X'){f[now][j] = new Info(0,0);}else{f[now][j] = MaxInfo(f[last][j],f[last][j+1],f[now][j+1]);f[now][j].maxScores += (f[now][j].maxScores == 0 ) ? 0 :map[i][j] - '0';}}}//如果最后结果不为0,也就是没有全面封死,要把起始1减掉int maxScore = f[now][0].maxScores != 0 ? f[now][0].maxScores-1 : 0;return new int[]{maxScore,f[now][0].maxways};}public Info MaxInfo(Info a,Info b,Info c){int maxScore = 0;int maxway = 0;maxScore = Math.max(a.maxScores,Math.max(b.maxScores,c.maxScores));if(maxScore == a.maxScores) maxway += a.maxways;if(maxScore == b.maxScores) maxway += b.maxways;if(maxScore == c.maxScores) maxway += c.maxways;return new Info(maxScore % MOD,maxway % MOD);}class Info{int maxScores;int maxways;public Info(int maxScores,int maxways){this.maxScores = maxScores;this.maxways = maxways;}}}
