📜  门|门CS 2011 |第 61 题(1)

📅  最后修改于: 2023-12-03 14:58:37.198000             🧑  作者: Mango

门|门CS 2011 |第 61 题

题目描述

题目链接:https://www.luogu.com.cn/problem/P1875

有一个大小为 $n \times m$ 的地图,每个格子上可能是 “#” 或者是 “.”。你要从左上角走到右下角,每一步只能向右或者往下走,且不能经过 “#” 的格子。请问有多少种不同的走法。

输入格式

第一行包含 2 个整数 $n,m$,表示地图的大小。

接下来 $n$ 行,每行包含一个长度为 $m$ 的字符串,描述地图。

输出格式

输出一个整数,表示可行的走法总数,答案对 $10^9+7$ 取模。

样例

输入:

3 3
..#
...
#..

输出:

2
题解

根据题目描述,可以使用动态规划求出解,具体做法如下:

设 $f(i,j)$ 表示从 $(1,1)$ 出发到 $(i,j)$ 的路径总数,那么可以得到状态转移方程为:

$$ f(i,j) = \begin{cases} f(i-1,j) + f(i,j-1),& (i,j) \text{为 "."} \ 0,& (i,j) \text{为 "#"} \end{cases} $$

边界条件为:

$$ f(1,1) = \begin{cases} 1,& (1,1) \text{为 "."} \ 0,& (1,1) \text{为 "#"} \end{cases} $$

最终的答案即为 $f(n,m)$,因为只能向右或向下走,所以最后一步要么从 $(n-1,m)$ 走到 $(n,m)$,要么从 $(n,m-1)$ 走到 $(n,m)$。

时间复杂度为 $O(nm)$。

完整代码如下(Python 版本):

MOD = 10**9+7

n, m = map(int, input().split())

# 初始化地图
g = []
for i in range(n):
    g.append(list(input()))

# 初始化状态数组
f = [[0] * (m+1) for _ in range(n+1)]
f[1][1] = 1

# 状态转移
for i in range(1, n+1):
    for j in range(1, m+1):
        if g[i-1][j-1] == '.':
            f[i][j] = (f[i-1][j] + f[i][j-1]) % MOD

print(f[n][m])

这里使用了 Python3 提供的多行输入和输入到二维列表的语法,具体解释可查阅 Python3 的官方文档。

参考文献