题意:

给你一个大小为的网格图,其中有一块矩形区域(左上角位置为,右下角位置为不能走,起点在处,每次你只能向右或者向下走,问最后走到终点有多少种方案?

解法一(DFS暴力枚举,不可AC)

我们可以用深度优先搜索算法枚举所有的路线,并且统计答案。
具体的:
    我们用递归函数表示当前走到点,接下来我们开始讨论:
    1. 点超出网格图范围,直接返回
    2. 点处在不可走的矩形区域范围,直接返回
    3. 点处在终点处,答案+1并返回
    4. 其他情况,分别扩展向右走和向下走两种情况,即
代码:
class Solution {
public:
    const int mod=1e9+7;
    int n,m,x0,y0,x1,y1;
    inline bool check(int i,int j){
        //判断点(i,j)是否不在矩形区域内
        return i<x0||j<y0||i>x1||j>y1;
    }
    int ans;
    void dfs(int i,int j){
        if(i<=0||i>n||j<=0||j>m||!check(i,j))return;//前两种情况
        if(i==n&&j==m){
            ans=(ans+1)%mod;//第三种情况
            return;
        }
        //其他情况,直接扩展
        dfs(i,j+1);
        dfs(i+1,j);
    }
    int GetNumberOfPath(int n, int m, int x0, int y0, int x1, int y1) {
        this->n=n,this->m=m,this->x0=x0,this->y0=y0,this->x1=x1,this->y1=y1;
        this->ans=0;
        dfs(1,1);//从起点开始扩展
        return ans;
    }
};
时间复杂度:,对于每个格子,有两种决策(向右走和向下走),根据乘法原理可得方案数为级别,故总的时间复杂度为
空间复杂度:,路线长度为,故递归深度为级别,故空间复杂度为

解法二(动态规划)

我们设表示从起点走到点的方案数,接下来我们分情况讨论:
    1. 显然
    2. 若点处在矩形范围内,则
    3. 其他情况我们考虑,每个点只会从上面下来和从左边过来
        
        则我们有
最后答案即为
代码:
class Solution {
public:
    const int mod=1e9+7;
    inline bool check(int i,int j,int x0,int y0,int x1,int y1){
        //判断点(i,j)是否可走
        return i<x0||i>x1||j<y0||j>y1;
    }
    int f[1005][1005];
    int GetNumberOfPath(int n, int m, int x0, int y0, int x1, int y1) {
        f[1][1]=1;//起点状态
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(i==1&&j==1)continue;//起点状态已经计算过了
                if(check(i,j,x0,y0,x1,y1)){
                    //当前点可以走
                    f[i][j]=(f[i-1][j]+f[i][j-1])%mod;
                }
            }
        }
        return f[n][m];//最后答案
    }
};
时间复杂度:,我们的状态数是的,每次转移的代价是的,故总的时间复杂度为
空间复杂度:,我们需要用一个大小为的二维数组保存状态,故总的空间复杂度为