LeetCode 576. Out of Boundary Paths
给你一个大小为 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 <= 500 <= startRow < m0 <= startColumn < n
算法
(动态规划) O(N⋅m⋅n) 定义状态 f(k,x,y) 表示从网格边界格子经过 k 步,到达格子 (x, y) 的方案数。 初始时,每个位于边界的格子 (x, y),其 f(0,x,y)=1;转移时,每个点可以从四个相邻的格子(如果存在)进行累加转移。 最终答案为,f(0,i,j)+f(1,i,j)+…+f(N−1,i,j)。由于规定边界的格子步数为 0,所以最多只能统计到 N−1步。
时间复杂度
状态数为 O(N⋅m⋅n),每个状态的转移数为 O(1),故总时间复杂度为 O(N⋅m⋅n)。
C++ 代码
class Solution {
public:
int mod = 1000000007;
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int findPaths(int m, int n, int N, int i, int j) {
if (N == 0)
return 0;
vector<vector<vector<int>>> f(N, vector<vector<int>>(m, vector<int>(n, 0)));
for (int x = 0; x < m; x++) {
f[0][x][0] ++;
f[0][x][n - 1]++;
}
for (int y = 0; y < n; y++) {
f[0][0][y]++;
f[0][m - 1][y]++;
}
for (int k = 1; k < N; k++)
for (int x = 0; x < m; x++)
for (int y = 0; y < n; y++)
for (int t = 0; t < 4; t++) {
int u = x + dx[t], v = y + dy[t];
if (u < 0 || u >= m || v < 0 || v >= n)
continue;
f[k][x][y] = (f[k][x][y] + f[k - 1][u][v]) % mod;
}
int ans = 0;
for (int k = 0; k < N; k++)
ans = (ans + f[k][i][j]) % mod;
return ans;
}
};