这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
576. 出界的路径数
给你一个大小为 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 <= 500 <= maxMove <= 50
0 <= startRow < m0 <= startColumn < n
方法一
一开始直接暴力,超时了;
动态规划:
- 状态表示:
f[i][j][k]表示,从下标为i和j开始,最多走k步的方案,值为方案的数量; - 状态转移:从最后一步入手,在下标为
i和j时,能转移到该位置的只有上下左右四个方位,因为状态转移方程可以写为 f[i][j][k] += f[i-1][j][k-1] + f[i+1][j][k-1] + f[i][j-1][[k-1] + f[i][j+1][k-1]- 最后要特判一下边界条件,当横坐标或者纵坐标有一个为边界,且此时能移动的步数
k为1时,此时的f[i][j][k]加1;
class Solution {
public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {
final int mod = 1000000007;
int[][][] f = new int[m][n][maxMove + 1];
int[] dx = new int[]{0,0,1,-1};
int[] dy = new int[]{1,-1,0,0};
for (int k = 1; k <= maxMove; k ++ ){
for (int i = 0; i < m; i ++ )
for (int j = 0; j < n; j ++ )
for (int u = 0; u < 4; u ++ ) {
int a = i + dx[u], b = j + dy[u];
if (a < 0 || b < 0 || a == m || b == n){
if (k == 1)
f[i][j][k] = (f[i][j][k] + 1) % mod;
}
else {
f[i][j][k] = (f[i][j][k] + f[a][b][k - 1]) % mod;
}
}
}
int res = 0;
for (int i = 1; i <= maxMove; i ++ )
res = (res + f[startRow][startColumn][i]) % mod;
return res;
}
}
时间复杂度: O(nmk)
空间复杂度: O(nmk)