📜  骑士留在棋盘上的概率(1)

📅  最后修改于: 2023-12-03 15:28:59.401000             🧑  作者: Mango

骑士留在棋盘上的概率

问题描述

假设一个 $n\times n$ 的棋盘上有一个骑士(也叫马)位于某个方格中。骑士每次可以沿着 L 字形走法移动两个格子(即横向移动 2 个格子、纵向移动 1 个格子或横向移动 1 个格子、纵向移动 2 个格子),并且可以在棋盘外面跳出去。求骑士经过 $k$ 步后仍停留在棋盘上的概率。

解法

首先,我们可以发现骑士在棋盘上的位置是有限的,总共只有 $n^2$ 种可能的位置。骑士每次可以沿着 L 字形走法移动两个格子,因此,每个位置最多可以有 $8$ 种可能的下一步位置。

为了求出骑士经过 $k$ 步后仍停留在棋盘上的概率,我们可以使用动态规划。

设 $dp[i][j][t]$ 表示骑士经过 $t$ 步后到达 $(i,j)$ 的概率,其中 $1\leq i,j \leq n$,$t\leq k$。那么最终的答案即为 $\sum\limits_{i=1}^n \sum\limits_{j=1}^n dp[i][j][k]$。

对于 $dp[i][j][t]$,可以根据下一步的位置 $(x,y)$ 来更新:

$$ dp[x][y][t+1] += \frac{dp[i][j][t]}{8} $$

注意边界条件,如果下一步 $(x,y)$ 跳出了棋盘,则在 $dp[i][j][t]$ 中减掉对应的概率即可。

代码实现

Python 代码实现如下:

def knight_probability(n: int, k: int, r: int, c: int) -> float:
    dp = [[[0] * (k + 1) for _ in range(n + 2)] for _ in range(n + 2)]
    dp[r][c][0] = 1
    for t in range(k):
        for i in range(1, n + 1):
            for j in range(1, n + 1):
                if dp[i][j][t]:
                    for dx, dy in [(2, 1), (1, 2), (-1, 2), (-2, 1), (-2, -1), (-1, -2), (1, -2), (2, -1)]:
                        x, y = i + dx, j + dy
                        if 1 <= x <= n and 1 <= y <= n:
                            dp[x][y][t + 1] += dp[i][j][t] / 8
                        else:
                            dp[i][j][t + 1] += dp[i][j][t] / 8
    return sum(dp[i][j][k] for i in range(1, n + 1) for j in range(1, n + 1))

代码的时间复杂度为 $O(n^2 k)$,空间复杂度为 $O(n^2 k)$。

参考文献