Skip to content

Commit f9fd14b

Browse files
committed
Finally worked
1 parent fc3474a commit f9fd14b

File tree

1 file changed

+38
-16
lines changed

1 file changed

+38
-16
lines changed
Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,72 @@
11
# 913. Cat and Mouse
22
# https://leetcode.com/problems/cat-and-mouse/
3-
# Dunno
4-
# 05/12/2025
3+
# Minimax, memoization
4+
# 06/12/2025
55

6-
7-
# Note: This is sadly TLE
8-
# 70 cases passed
6+
# Draw positions use many more turns, so I use a limit to detect them.
7+
# The issue is that if I put turns in the memo keys, then even winning/losing
8+
# states get recalculated for each turn.
9+
# My solution: I memoize separately the non-draw states (wins/loss)
10+
# without turns. So:
11+
# * wins/losses are instantly recognized,
12+
# * only draws use the turn limit,
13+
# * and the algo becomes much faster.
914
class Solution:
1015
def catMouseGame(self, graph) -> int:
1116
from functools import cache
1217
MOUSE_WINS = 1
1318
CAT_WINS = 2
1419
DRAW = 0
1520
REFUGE = 0
16-
limit = 4 * len(graph)
21+
MAX_TURNS = 4 * len(graph)
1722

18-
def wins(isCat):
23+
def win(isCat):
1924
if isCat: return CAT_WINS
20-
else:
21-
return MOUSE_WINS
25+
else: return MOUSE_WINS
2226

23-
@cache
27+
# Separate memory for non-draw states (wins/losses)
28+
# This caches without turns
29+
helper = {}
30+
31+
@cache #Caches all
2432
def solve(mouse=1, cat=2, isCat=False, turns=0):
33+
helperKey = (mouse, cat, isCat)
2534
if mouse == cat: return CAT_WINS
2635
if mouse == REFUGE: return MOUSE_WINS
27-
if turns >= limit: return DRAW
36+
37+
# Turn limit forces to detect draws
38+
if turns >= MAX_TURNS: return DRAW
39+
40+
# Check helper for previous wins/losses
41+
if helperKey in helper:
42+
return helper[helperKey]
2843

44+
# Explore all possible moves for current player
2945
newMouse = mouse
3046
newCat = cat
3147
foundDraw = False
3248
for nxt in graph[cat if isCat else mouse]:
3349
if isCat:
34-
if nxt == 0: continue
50+
if nxt == REFUGE: continue # Cat cannot enter refuge
3551
newCat = nxt
3652
else:
3753
newMouse = nxt
3854
res = solve(newMouse, newCat, not isCat, turns + 1)
39-
if res == wins(isCat):
55+
# If current player finds a winning move, takes it
56+
if res == win(isCat):
57+
helper[helperKey] = res
4058
return res
41-
59+
# Track if there is at least one draw
4260
if res == DRAW:
4361
foundDraw = True
44-
62+
63+
# No wins here
64+
# If found at least one draw, choose draw
4565
if foundDraw:
4666
return DRAW
4767

48-
return wins(not isCat)
68+
# No wins or draws found, opponent wins
69+
helper[helperKey] = win(not isCat)
70+
return win(not isCat)
4971

5072
return solve()

0 commit comments

Comments
 (0)