📅  最后修改于: 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)$。