LeetCode每日一题 576. 出界的路径数

315 阅读2分钟

这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

576. 出界的路径数

给你一个大小为 m x n 的网格和一个球。球的起始坐标为 [startRow, startColumn] 。你可以将球移到在四个方向上相邻的单元格内(可以穿过网格边界到达网格之外)。你 最多 可以移动 maxMove 次球。

给你五个整数 mnmaxMovestartRow 以及 startColumn ,找出并返回可以将球移出边界的路径数量。因为答案可能非常大,返回对 109 + 7 取余 后的结果。

示例 1:

img

输入:m = 2, n = 2, maxMove = 2, startRow = 0, startColumn = 0
输出:6

示例 2:

img

输入:m = 1, n = 3, maxMove = 3, startRow = 0, startColumn = 1
输出:12

提示:

  • 1 <= m, n <= 50
  • 0 <= maxMove <= 50
  • 0 <= startRow < m
  • 0 <= startColumn < n

方法一

一开始直接暴力,超时了;

image-20210815093141901

动态规划:

  • 状态表示:f[i][j][k]表示,从下标为ij开始,最多走k步的方案,值为方案的数量;
  • 状态转移:从最后一步入手,在下标为ij时,能转移到该位置的只有上下左右四个方位,因为状态转移方程可以写为
  • 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)