DFS

  1. class Solution {
  2. int MOD = (int)1e9+7;
  3. int[][][] cache;
  4. int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
  5. int dfs(int m, int n, int move, int x, int y){
  6. //base case 1:出界了
  7. if(x < 0 || x >= m || y < 0 || y >= n){
  8. return 1;
  9. }
  10. //base case 2:次数用完了,没出界,证明不是合法路径
  11. if(move == 0){
  12. return 0;
  13. }
  14. if(cache[x][y][move] != -1){
  15. return cache[x][y][move];
  16. }
  17. cache[x][y][move] = 0;
  18. for(int i = 0; i < 4; i++){
  19. int newX = x + dirs[i][0];
  20. int newY = y + dirs[i][1];
  21. cache[x][y][move] += dfs(m, n, move - 1, newX, newY);
  22. cache[x][y][move] %= MOD;
  23. }
  24. return cache[x][y][move];
  25. }
  26. public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {
  27. cache = new int[m][n][maxMove + 1];
  28. for(int i = 0; i < m; i++){
  29. for(int j = 0; j < n; j++){
  30. Arrays.fill(cache[i][j], -1);
  31. }
  32. }
  33. return dfs(m, n, maxMove, startRow, startColumn);
  34. }
  35. }

DP

  1. class Solution {
  2. int mod = (int)1e9+7;
  3. int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
  4. //获取边界点(x, y)对应的出界路径数
  5. int getBaseCase(int m, int n, int x, int y){
  6. int sum = 0;
  7. sum += (x == 0 ? 1 : 0);
  8. sum += (x == m - 1 ? 1 : 0);
  9. sum += (y == 0 ? 1 : 0);
  10. sum += (y == n - 1 ? 1 : 0);
  11. return sum;
  12. }
  13. public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {
  14. //状态定义
  15. //dp[i][j][k]代表处于(i, j)且当前移动次数为k的出界路径数
  16. int[][][] dp = new int[m][n][maxMove + 1];
  17. //状态初始化
  18. //预处理所有边界格子的出界路径数
  19. for(int i = 0; i < n; i++){//处理第一行和最后一行
  20. //第一行的第i列
  21. int case1 = getBaseCase(m, n, 0, i);
  22. //第m行的第i列
  23. int case2 = getBaseCase(m, n, m - 1, i);
  24. //对所有移动次数>=1的情况,处于边界点都+1
  25. for(int k = 1; k <= maxMove; k++){
  26. dp[0][i][k] = case1;
  27. dp[m - 1][i][k] = case2;
  28. }
  29. }
  30. for(int i = 0; i < m; i++){//处理第一列和最后一列
  31. //第1列的第i行
  32. int case1 = getBaseCase(m, n, i, 0);
  33. //第n列的第i行
  34. int case2 = getBaseCase(m, n, i, n - 1);
  35. for(int k = 1; k <= maxMove; k++){
  36. dp[i][0][k] = case1;
  37. dp[i][n - 1][k] = case2;
  38. }
  39. }
  40. //状态转移
  41. //dp[i][j][k] = dp[i-1][j][k-1] + dp[i][j-1][k-1] + dp[i+1][j][k-1] + dp[i][j+1][k-1]
  42. //最外循环枚举移动次数k
  43. for(int k = 1; k <= maxMove; k++){
  44. for(int i = 0; i < m; i++){
  45. for(int j = 0; j < n; j++){
  46. //尝试上、下左、右四个方向
  47. for(int it = 0; it < 4; it++){
  48. int x = i + dirs[it][0];
  49. int y = j + dirs[it][1];
  50. if(x >= 0 && x < m && y >= 0 && y < n){
  51. dp[i][j][k] += dp[x][y][k -1];
  52. dp[i][j][k] %= mod;
  53. }
  54. }
  55. }
  56. }
  57. }
  58. return dp[startRow][startColumn][maxMove];
  59. }
  60. }

收获:尝试从记忆化搜索转化为DP,并且考虑如何从base case找到对应的dp数组初始化。