题目要求
有一个m*n的网格,网格中有一个小球。小球初始位置位[startRow,startColumn]。您可以将小球移动到网格中相邻的四个单元格之一(可能会越过网格边界移出网格)。最多可以对小球进行maxMove移动。
给定 m、n、maxMove、startRow、startColumn 这五个整数,返回将小球移出网格边界的路径数。由于答案可能非常大,因此请返回 的模数。
Example 1:
Input: m = 2, n = 2, maxMove = 2, startRow = 0, startColumn = 0 Output: 6
Example 2:
Input: m = 1, n = 3, maxMove = 3, startRow = 0, startColumn = 1 Output: 12
思路
这个题目有三个状态:横坐标、纵坐标和可移动的次数,所以我们可以用一个三维的dp数组存储这三个状态或者一个带有三个参数的dp函数。
状态转移关系:在maxMove步之内从(i,j)位置踢出界外的路径数量等于在maxMove-1步之内从(i,j)的相邻位置踢出界外的路径数量之和。(相邻位置多走一步可以到达i,j)
注意处理计算的冗余和基础情况。这里的递归采用的是数组和递归函数相结合的方式。参考labuladong的思路和题解。
代码
class Solution {
public:
int memo[50][50][51];
int m, n;
int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {
this->m = m;
this->n = n;
memset(memo, -1, sizeof(memo));
return dp(maxMove, startRow, startColumn);
}
int dp(int maxMove, int i, int j) {
// base case,找到一条出界路径
if (i < 0 || j < 0 || i >= m || j >= n) {
return 1;
}
// 避免冗余计算
if (memo[i][j][maxMove] != -1) {
return memo[i][j][maxMove];
}
// 无法在有限的步数内出界
if (maxMove == 0) {
return 0;
}
// 状态转移关系:
// 在maxMove步之内从(i,j)踢出界外的路径数量等于
// 在maxMove-1步之内从(i,j)的相邻位置出界的路径数量之和;
long res = 0;
res += dp(maxMove - 1, i-1, j);
res += dp(maxMove - 1, i+1, j);
res += dp(maxMove - 1, i, j-1);
res += dp(maxMove - 1, i, j+1);
memo[i][j][maxMove] = (int)(res % 1000000007);
return memo[i][j][maxMove];
}
};