This commit is contained in:
parent
c3c73ee517
commit
f965eea33a
@ -1,7 +1,7 @@
|
|||||||
|
import heapq
|
||||||
|
from collections import defaultdict
|
||||||
from typing import Any, Iterator, TypeAlias
|
from typing import Any, Iterator, TypeAlias
|
||||||
|
|
||||||
import networkx as nx
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
Position: TypeAlias = tuple[int, int]
|
Position: TypeAlias = tuple[int, int]
|
||||||
@ -18,41 +18,45 @@ class Solver(BaseSolver):
|
|||||||
target = next(
|
target = next(
|
||||||
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "E"
|
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "E"
|
||||||
)
|
)
|
||||||
facing = (0, 1)
|
|
||||||
|
|
||||||
G = nx.DiGraph()
|
queue: list[tuple[int, Position, Direction, tuple[Position, ...]]] = [
|
||||||
|
(0, rein, (0, 1), (rein,))
|
||||||
|
]
|
||||||
|
|
||||||
for i in range(1, n_rows - 1):
|
max_score = n_rows * n_cols * 1000
|
||||||
for j in range(1, n_cols - 1):
|
target_score: int = max_score
|
||||||
if grid[i][j] == "#":
|
scores: dict[tuple[Position, Direction], int] = defaultdict(lambda: max_score)
|
||||||
continue
|
visited: set[Position] = set()
|
||||||
|
|
||||||
for di, dj in ((-1, 0), (0, 1), (1, 0), (0, -1)):
|
while queue:
|
||||||
if grid[i + di][j + dj] != "#":
|
score, pos, dir, path = heapq.heappop(queue)
|
||||||
G.add_edge(
|
|
||||||
((i, j), (di, dj)), ((i + di, j + dj), (di, dj)), weight=1
|
|
||||||
)
|
|
||||||
|
|
||||||
if di == 0:
|
if target_score < score:
|
||||||
G.add_edge(((i, j), (di, dj)), ((i, j), (1, 0)), weight=1000)
|
break
|
||||||
G.add_edge(((i, j), (di, dj)), ((i, j), (-1, 0)), weight=1000)
|
|
||||||
else:
|
|
||||||
G.add_edge(((i, j), (di, dj)), ((i, j), (0, 1)), weight=1000)
|
|
||||||
G.add_edge(((i, j), (di, dj)), ((i, j), (0, -1)), weight=1000)
|
|
||||||
|
|
||||||
for di, dj in ((-1, 0), (0, 1), (1, 0), (0, -1)):
|
if pos == target:
|
||||||
G.add_edge((target, (di, dj)), (target, (-1, -1)), weight=0)
|
target_score = score
|
||||||
|
visited |= set(path)
|
||||||
|
continue
|
||||||
|
|
||||||
yield nx.shortest_path_length(
|
scores[pos, dir] = score
|
||||||
G,
|
|
||||||
source=(rein, facing),
|
|
||||||
target=(target, (-1, -1)),
|
|
||||||
weight="weight",
|
|
||||||
)
|
|
||||||
|
|
||||||
nodes: set[tuple[int, int]] = set()
|
row, col = pos
|
||||||
for path in nx.all_shortest_paths(
|
d_row, d_col = dir
|
||||||
G, source=(rein, facing), target=(target, (-1, -1)), weight="weight"
|
|
||||||
):
|
for cost, n_pos, n_dir in (
|
||||||
nodes.update(position for position, _ in path)
|
(1, (row + d_row, col + d_col), dir),
|
||||||
yield len(nodes)
|
(1000, pos, (1, 0) if d_row == 0 else (0, 1)),
|
||||||
|
(1000, pos, (-1, 0) if d_row == 0 else (0, -1)),
|
||||||
|
):
|
||||||
|
n_row, n_col = n_pos
|
||||||
|
score_n = score + cost
|
||||||
|
if grid[n_row][n_col] != "#" and score_n < scores[n_pos, n_dir]:
|
||||||
|
heapq.heappush(
|
||||||
|
queue,
|
||||||
|
(score_n, n_pos, n_dir, path + (n_pos,)),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert target_score is not None
|
||||||
|
yield target_score
|
||||||
|
yield len(visited)
|
||||||
|
Loading…
Reference in New Issue
Block a user