题目
给你一个大小为 m x n 的网格和一个球。球的起始坐标为 [startRow, startColumn] 。你可以将球移到在四个方向上相邻的单元格内(可以穿过网格边界到达网格之外)。你 最多 可以移动 maxMove 次球。
给你五个整数 m、n、maxMove、startRow 以及 startColumn ,找出并返回可以将球移出边界的路径数量。因为答案可能非常大,返回对
1
0
9
+
7
10^9 + 7
109+7取余 后的结果。
示例 1:
输入:m = 2, n = 2, maxMove = 2, startRow = 0, startColumn = 0
输出:6
示例 2:
输入:m = 1, n = 3, maxMove = 3, startRow = 0, startColumn = 1
输出:12
提示:
- 1 <= m, n <= 50
- 0 <= maxMove <= 50
- 0 <= startRow < m
- 0 <= startColumn < n
题解
方法一:记忆化递归
这里直接递归会超时,需要使用cache数组记下每次得到的结果,避免重复计算。
cache[i][j][k]表示还剩下 k 步时,到 (i,j) 的路径数量。
class Solution {
int MOD = (int)1e9+7;
int[][] dirs = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
int[][][] cache;
public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {
cache = new int[m][n][maxMove + 1];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k <= maxMove; k++) {
cache[i][j][k] = -1;
}
}
}
return dfs(m, n, startRow, startColumn, maxMove);
}
int dfs(int m, int n, int x, int y, int k) {
if (x < 0 || x >= m || y < 0 || y >= n) return 1;
if (k == 0) return 0;
if (cache[x][y][k] != -1) return cache[x][y][k]; // 如果是已经计算出的结果就直接返回
int ans = 0;
for (int[] d : dirs) {
int nx = x + d[0], ny = y + d[1];
ans += dfs(m, n, nx, ny, k - 1); // 递归
ans %= MOD;
}
cache[x][y][k] = ans; // 保存已经计算出的结果
return ans;
}
}