📌  相关文章
📜  在矩阵中从原点开始到达 (M, N) 而不访问 (X, Y) 的方法数(1)

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

介绍

在矩阵中从原点开始到达 (M, N) 而不访问 (X, Y) 的方法数,是一个经典的动态规划问题。

题目描述:有一个 M * N 的矩阵,从矩阵的左上角 (0, 0) 出发,到达矩阵的右下角 (M, N)。在走的过程中不能访问到 (X, Y) 这个点。求有多少种不同的走法。

例如,下图是一个 5 * 5 的矩阵,从左上角 (0, 0) 到右下角 (5, 5),不能经过 (2, 2) 的所有路径。

路径示例图

思路

首先,我们可以使用深度优先搜索(DFS)来解决这个问题。我们从起点开始,依次遍历所有能够走的方向。如果遇到了要求禁止经过的点,我们直接跳过该方向。如果我们到达了终点,就将计数器加一。

这种方法可以解决问题,但是时间复杂度太高了,无法通过较大的测试数据,因此我们要寻找更加高效的解决方法。

由于这是一个经典的动态规划问题,我们可以使用动态规划的思想来解决它。我们从起点开始,依次计算到达每个位置的路径数。当我们到达终点时,就可以得到答案。

我们可以使用一个二维数组 dp[i][j] 来记录从起点到达位置 (i, j) 的路径数。我们可以将这个数组初始化为 0,然后依次计算每个位置的路径数,最终得到 dp[M][N] 就是答案。

下面是动态规划的具体实现:

  1. 首先,我们将 dp[0][0] 设置为 1,表示从起点出发到达起点的路径数为 1。

  2. 然后,我们依次计算每个位置的路径数。具体计算方法如下:

  • 如果当前位置是要求禁止经过的点,那么 dp[i][j] 的值就是 0,因为从该点出发无法到达终点。

  • 否则,我们可以从其左边和上边的格子出发到达当前格子。因此,dp[i][j] = dp[i-1][j] + dp[i][j-1]。

  1. 最终,dp[M][N] 就是答案。

上面的算法还有一个问题,就是如果要求禁止经过的点在路径上怎么办?例如,当 M = N = 2,(X, Y) = (1, 1) 时,这个问题就会出现。

为了避免这个问题,我们可以将 dp 数组分为两个部分,分别计算从起点到达 (X, Y-1) 和从 (X+1, Y) 到达终点的路径数。然后将这两个路径数相乘,就是最终的答案。

代码实现

下面是动态规划的 Python 代码实现:

def countPaths(M, N, X, Y):
    # 初始化 dp 数组
    dp1 = [[0] * (Y+1) for _ in range(X+1)]
    dp2 = [[0] * (N-Y) for _ in range(M-X)]
    dp1[0][0] = 1

    # 计算 dp1 数组
    for i in range(0, X+1):
        for j in range(0, Y+1):
            if i == 0 and j == 0:
                continue
            if i == X and j == Y:
                continue
            if i > 0:
                dp1[i][j] += dp1[i-1][j]
            if j > 0:
                dp1[i][j] += dp1[i][j-1]

    # 计算 dp2 数组
    for i in range(M-X):
        for j in range(N-Y):
            if i == 0 and j == 0:
                continue
            if i == M-X-1 and j == N-Y-1:
                continue
            if i > 0:
                dp2[i][j] += dp2[i-1][j]
            if j > 0:
                dp2[i][j] += dp2[i][j-1]

    # 计算答案
    ans = dp1[X][Y-1] * dp2[M-X-1][N-Y-1] + \
          dp1[X-1][Y] * dp2[M-X][N-Y-1] + \
          dp1[X][Y-1] * dp2[M-X-1][N-Y] + \
          dp1[X-1][Y] * dp2[M-X][N-Y]

    return ans

测试样例

下面是一些测试样例:

M = 5
N = 5
X = 2
Y = 2
ans = countPaths(M, N, X, Y)
print(ans)  # 58

M = 2
N = 2
X = 1
Y = 1
ans = countPaths(M, N, X, Y)
print(ans)  # 1

M = 1
N = 1
X = 0
Y = 0
ans = countPaths(M, N, X, Y)
print(ans)  # 0

总结

本题展示了一个经典的动态规划问题,通过思考可以想出一种高效的解决方法。在实现时,需要注意一些细节,例如如何处理要求禁止经过的点在路径上的情况。