Exhaustive search. A minimax algorithm with full exhaustive search is a slow solution with no simple implementation. With the following observation, an exhaustive search solution becomes much cleaner and easier to implement. It doesn't make sense to block a passage after cleaning some other passage. Cleaning the passage increases the mouse's movement options, therefore Dumbo would be better off blocking the other passage before cleaning one.
If Dumbo leaves the mouse running, it will eventually get stuck. Before the mouse gets stuck, Dumbo will only block passages. Which ones should be blocked is a matter of the exhaustive search. Once the mouse is stuck, Dumbo will block all the side passages leading away from the path to the trap and then clean that path. The mouse will have no choice but to run directly into the trap.
Mouse starts the game next to the trap. Root the tree so that the root corresponds to the trap. What happens if Dumbo just leaves the mouse running until it gets stuck? The mouse will get stuck in one of the leaves, Dumbo will block all the side edges on the path leading from this leaf to the root and then clean the dirty edges in this path.
We can calculate the exact number of moves Dumbo needs to win the game if the mouse is caught in a certain leaf. Let's call this the weight of the leaf and denote the weight of a leaf
with
. Note that if Dumbo leaves the mouse running around, it will move to the leaf with the largest weight. On the other hand, Dumbo will try to block the mouse from reaching leaves with large weights.
Suppose the mouse is in node
. Because the mouse starts at depth
, we can safely assume it only moves down the tree towards the leaves. Node
has
children
. Without loss of generality, we assume that
is the optimal choice for the mouse and
the second best. Dumbo will want to block the passage to node
. Does this affect weights of the leaves in subtrees
? Because edge
is a side edge from a path from any leaf in subtrees
to the root, it's already part of their weights and the edge
has to be blocked anyway. So blocking the passage next to the mouse doesn't change the weights of the leaves in the subtrees. Hence, Dumbo will block the best possible child of the node and mouse will traverse the second best.
From here on, we can generalize the definition of weights for any node. Weight of a node
is the number of moves Dumbo needs to win if it's his turn and the mouse is currently in node
. Dumbo will block the edge to the heaviest child and the mouse will traverse the edge to the second heaviest one. Hence, weight of a node
is the weight of second heaviest child or
if
only has one child. Weights of nodes can easily be calculated with one tree traversal which takes linear time. The number of moves in the game is equal to the weight of the mouse's starting node.
General case. How does the game change in the general case? The mouse doesn't start the game at depth
, which means it might make a few moves up the tree before going down. Dumbo cannot block upgoing edge, because he would block mouse from reaching the trap. As soon as the mouse makes a move down the tree, the game continues as described in the previous section.
When selecting the next edge to block, Dumbo must therefore not limit himself to outgoing edges of the mouse's current location. Possible candidates are also the side passage on the path from the mouse to the trap.
In the starting position of the game, a path
leads from the mouse to the trap. Dumbo may not block edges in
, so weights of nodes in
are undefined. There are multiple subtrees attached to
. Each of these subtrees (actually their roots) has its weight as defined in the previous section.
Suppose the mouse arrives into a subtree
. Any blockade Dumbo made on side edges of
below the depth of
does not count towards its weight
. Let's say there were
such moves, therefore Dumbo has to make
moves in total. What is the minimal
if Dumbo plays optimally?
We can find this by a binary search over the total number of Dumbo's moves. Whether Dumbo can win in at most
moves can be verified by simulating a mouse's run up the path
and testing if all the side edges
with
have been blocked.
We can present each subtree
with pair
, where
is distance of subtree
from node
. Dumbo can only block path to this subtree in the first
rounds, then the mouse reaches it. We sort pairs by first component. Let
be this sorted list of pairs. We will use variable
to count the number of blocked side paths. Initially,
.
For each pair
in
: If
, the passage has to be blocked and
. If at any point
and
, mouse reached a subtree before Dumbo could block the passage to it, which means Dumbo can't win in
moves. Otherwise, we found a way for Dumbo to win in
moves.
Each bisection iteration takes linear time (the list
doesn't change, it can be reused multiple times). Hence, total running time is
.
Comments