给你一个大小为 m x n 的网格和一个球。球的起始坐标为 [startRow, startColumn] 。你可以将球移到在四个方向上相邻的单元格内(可以穿过网格边界到达网格之外)。你 最多 可以移动 maxMove 次球。
给你五个整数 m、n、maxMove、startRow 以及 startColumn ,找出并返回可以将球移出边界的路径数量。因为答案可能非常大,返回对 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
class Solution {int mod = (int)1e9 + 7;int m, n;int[] dx = new int[]{-1, 0, 1, 0}, dy = new int[]{0, 1, 0, -1};//暴力dfs会超时,所以需要记忆化搜索int[][][] cache;public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {this.m = m; this.n = n;cache = new int[m + 1][n + 1][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(startRow, startColumn, maxMove);}int dfs(int x, int y, int k) {//说明到达了外面if (x < 0 || x >= m || y < 0 || y >= n) return 1;//没有步数直接返回0if (k == 0) return 0;//记忆化if (cache[x][y][k] != -1) return cache[x][y][k];//四个方向扩展int sum = 0;for (int i = 0; i < 4; ++i) {sum += dfs(x + dx[i], y + dy[i], k - 1);sum %= mod;}cache[x][y][k] = sum;return sum;}}
dp
class Solution {/**f[i][j][k] : 当前位置是[i, j],在步数最多是k的情况下移出网格的路径书考虑把维度缩小,用idx = i * m + j表示坐标状态转移:f[i][j][k] = f[i - 1][j][k - 1] + f[i][j - 1][k - 1] + f[i + 1][j][k - 1] + f[i][j + 1][k -1]初始化,把矩阵边缘都初始化为1, 不过需要注意矩阵顶点是有两条路径到外面的*/int m, n, maxMove;int mod = (int)1e9 + 7;int[] dx = new int[]{-1, 0, 1, 0}, dy = new int[]{0, 1, 0, -1};int[][] f;public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {this.m = m; this.n = n; this.maxMove = maxMove;f = new int[m * n + 1][maxMove + 1];//初始化for (int i = 0; i < m; ++i)for (int j = 0; j < n; ++j)for (int k = 1; k <= maxMove; ++k) {//注意k 是 从1开始, 因为在边缘必须还要移动一格if (i == 0) add(i, j, k);if (i == m - 1) add(i, j, k);if (j == 0) add(i, j, k);if (j == n - 1) add(i, j, k);}//dp过程,先从小到大枚举步数,因为我们依赖步数 - 1for (int i = 1; i <= maxMove; ++i)for (int idx = 0; idx < m * n; ++idx) {int[] t = parse(idx);int x = t[0], y = t[1];for (int j = 0; j < 4; ++j) {int a = x + dx[j], b = y + dy[j];if (a < 0 || a >= m || b < 0 || b >= n) continue;int nidx = get(a, b);f[idx][i] += f[nidx][i - 1];f[idx][i] %= mod;}}return f[get(startRow, startColumn)][maxMove];}int get(int x, int y) {return x * n + y;}int[] parse(int idx) {return new int[]{idx / n, idx % n};}void add(int i, int j, int k) {f[get(i, j)][k] ++;}}
