2
def canMouseWin(self, A: List[str], cj: int, mj: int) -> bool:3
# some helper functions:4
xy2i = lambda x, y: x * n + y5
i2xy = lambda i: (i // n, i % n)7
def adj_grid(x0, y0, jump=1):8
for dx, dy in ((-1, 0), (1, 0), (0, -1), (0, 1)):9
for step in range(jump):10
x, y = x0 + (step + 1) * dx, y0 + (step + 1) * dy11
if not (0 <= x < m and 0 <= y < n) or A[x][y] == "#":15
m, n, jps = len(A), len(A[0]), (mj, cj)16
fi = mi = ci = 0 # location of food, mouse, cat26
# BFS for unreachable food cases28
B = [list(row) for row in A]30
que = collections.deque([(x, y)])32
for x, y in adj_grid(*que.popleft()):41
if not reach_food(*i2xy(mi)):43
elif not reach_food(*i2xy(ci)):46
# adjacent states counter47
adj = [[[0] * (m * n) for _ in range(m * n)] for _ in range(2)]48
for i0 in range(m * n):52
for x, y in adj_grid(*i2xy(i0), jps[k]):53
adj[k][i[0]][i[1]] += 155
for i2[1 - k] in range(m * n):56
adj[k][i2[0]][i2[1]] = adj[k][i[0]][i[1]]58
dp = [[[None] * (m * n) for _ in range(m * n)] for _ in range(2)]62
) # que1 for decisive states, que2 for indecisive ones63
for i in range(m * n):68
dp[0][fi][i] = dp[1][fi][i] = True69
que1.append((1, fi, i))70
que2.append((0, fi, i))71
dp[0][i][fi] = dp[1][i][fi] = dp[0][i][i] = dp[1][i][i] = False72
que1.append((0, i, fi))73
que2.append((1, i, fi))74
que1.append((0, i, i))75
que2.append((1, i, i))79
k2, mi2, ci2 = que1.popleft()83
for x, y in adj_grid(*i2xy(i[k]), jps[k]):85
if dp[k][i[0]][i[1]] is None:86
dp[k][i[0]][i[1]] = t # directly determine the value87
if (k, i[0], i[1]) == (0, mi, ci):89
que2.append((k, i[0], i[1]))91
k2, mi2, ci2 = que2.popleft()95
for x, y in adj_grid(*i2xy(i[k]), jps[k]):97
if dp[k][i[0]][i[1]] is None:98
adj[k][i[0]][i[1]] -= 1 # only change the counter99
if adj[k][i[0]][i[1]] == 0:100
dp[k][i[0]][i[1]] = t101
if (k, i[0], i[1]) == (0, mi, ci):103
que1.append((k, i[0], i[1]))