题目
给你一个大小为 m x n 的网格和一个球。球的起始坐标为 [startRow, startColumn] 。你可以将球移到在四个方向上相邻的单元格内(可以穿过网格边界到达网格之外)。你 最多 可以移动 maxMove 次球。
给你五个整数 m、n、maxMove、startRow 以及 startColumn ,找出并返回可以将球移出边界的路径数量。因为答案可能非常大,返回对 109 + 7 取余 后的结果。
提示:
1 <= m, n <= 50
0 <= maxMove <= 50
0 <= startRow < m
0 <= startColumn < n
思路
定义dp[i][j][k]表示坐标(i,j),最多移动k次,出界的路径数。当k位于最中间,k<i,k<j,k<m-i,k<n-j。时,怎么都无法出界。直接返回0。状态转移方程为:dp[i][j][k] += dp[i+x][j+y][k-1],x=0、1或-1,y=0、1或-1。
代码
class Solution {
vector<vector<vector<int>>> cache;
int mod = 1000000007;
public:
int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {
cache.assign(m,vector<vector<int>>(n,vector<int>(maxMove+1)));
findUPaths(m, n, maxMove, startRow, startColumn);
return cache[startRow][startColumn][maxMove];
}
int findUPaths(int m, int n, int maxMove, int startRow, int startColumn) {
if (maxMove < 0) {
return 0;
}
if (maxMove < startRow && maxMove < m - startRow && maxMove < startColumn && maxMove < n - startColumn) {
return 0;
}
if (startRow < 0 || startRow >= m || startColumn < 0 || startColumn >= n) {
return 1;
}
if(cache[startRow][startColumn][maxMove] != 0) return cache[startRow][startColumn][maxMove];
vector<vector<int>> directions = {{-1,0},{1,0},{0,-1},{0,1}};
for(auto& direction: directions) {
int row = startRow + direction[0];
int column = startColumn + direction[1];
cache[startRow][startColumn][maxMove] += findUPaths(m, n, maxMove-1, row, column);
cache[startRow][startColumn][maxMove] %= mod;
}
return cache[startRow][startColumn][maxMove];
}
};