描述
一个nxm的网格中,起点在(1,1),终点在(n,m),网格中有一块不能走的矩形区域,左下坐标为(x0,y0),右上坐标为(x1,y1),求从起点到终点的路径条数。

图片说明

示例1

输入:
4,4,2,2,3,3

返回值:
2

说明:
只有两条可达路径

思路

这道题是求从起点到一个格子的所有路径。大家看上面的红点所在的格子,想要到红点所在的格子有两条路:一是:从红点左侧的格子过来;二是:从红点下侧的格子过来;然后我想要知道 红点 左侧格子有几条路径,也是用同样的方法。这样看来,我想求某个格子的路径数量应该是如下公式:

  dp[m][n] = dp[m - 1][n] + dp[m][n - 1];  
  dp[m][n]: 某个格子的坐标;  
  dp[m - 1][n]:是格子左侧的格子路径数量;  
  dp[m][n - 1]:是格子下侧的格子路径数量;  

这么就是动态规划状态转移方程
动态规划除了状态转移方程还有一个重要的元素,那就是 初始值
这道题的初始值很好确定,dp[1][1] = 1。就是起点位置默认是一条路径。

AC代码

public int GetNumberOfPath (int n, int m, int x0, int y0, int x1, int y1) {
        // write code hereå
        if (m < 1 || n < 1) {
            return 0;
        }
        // 初始化dp数组
        int[][] dp = new int[n + 1][m + 1];å
        // 设置默认值
        dp[1][1] = 1;
        // 开始遍历所有格子
        for (int i = 1; i <= n; i ++) {
            for (int j = 1; j <= m; j ++) {
                if (i == 1 && j == 1) {
                    continue;
                }
                // 当遇到不能走的区域 跳过
                if (i >= x0 && i <= x1 && j >= y0 && j <= y1) continue;
                // 每个格子的路径条数 = 左侧数量 + 下侧数量
                dp[i][j] = (dp[i - 1][j] + dp[i][j - 1])%1000000007;
            }
        }
        return dp[n][m];
    }
  • 时间复杂度:O(m*n), m 和 n 分别是长宽,因为所有的格子都要遍历到。
  • 空间复杂度:O(m*n),要将这些格子存储到 dp[m][n],二维数组中。

最后

更多的刷题已经知识,大家可以来我的博客看一看