路径的方案数

 

 

输入输出样例

Sample Input

3 1
3 1

Sample Output

5

More Info

对于100%的数据,有N≤1000,M≤100000
一道基础的动态规划题目

首先,题目描述的重点在于每次只能移动到下方相邻的格子或者右方相邻的格子,所以,我们就可以得出结论:到达第n个格子的路径数量是这个格子左边的格子的路径数量+上边格子的路径数量。我们定义一个DP数组,DP[i][j](也就是状态)代表第M[i][j]个格子的路径数量,根据上面的推论,我们可以得出状态转移方程:DP[i][j] = DP[i-1][j]+DP[i][j-1];

然而之后我们会发现,我们还没有对题目中的障碍进行处理。对于障碍的处理其实是非常简单的。遇见障碍,这条路就走不通了,也就是不对这个格子进行计算。那么如何做到不对该格子进行计算呢?有两种解决方法。

第一种:

当障碍数量小的时候,这时候我们就可以把所有障碍的路径记录一下,在动态规划的过程中进行处理,也就是当i = x and j = y的时候跳过循环,时间复杂度为O(mn^2),记录障碍的空间复杂度为O(m)。

第二种:

当障碍数量大的时候,这时候我们就需要多花费一些空间了。其实我们可以把所有的障碍坐标映射到一个二维数组中,也就是构造一个Map,true表示无障碍,false表示有障碍。在输入障碍的时候将对应下标变成false。判断也就是当Map[i][j] = false的时候跳过循环。时间复杂度为O(n^2),二维数组的空间复杂度为O(n^2)。

所以我们就用第二种方法,代码如下:
题解
#include <cstdio>
using namespace std;
int f[1010][1010];
bool bz[1010][1010];
int n, m, x, y;

int main() {
    scanf("%d%d", &n, &m);
    while (m--) {
        scanf("%d%d", &x, &y);
        bz[x][y] = true;
    }
    f[1][1] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (bz[i][j]) {
                f[i][j] = 0;
                continue;
            }
            if (i > 1)
                f[i][j] = (f[i][j] + f[i - 1][j]) % 100003;
            if (j > 1)
                f[i][j] = (f[i][j] + f[i][j - 1]) % 100003;
        }
    }
    printf("%d", f[n][n]);
    return 0;
}
代码
//题解忘记是哪个大佬的了,写的很详细很棒,只是我找不到了。如果有侵权,请联系我删除。

posted @ 2021-02-03 21:18  月亮茶  阅读(67)  评论(0编辑  收藏  举报