2026-05-20 18:23:47 +00:00
|
|
|
|
import heapq
|
|
|
|
|
|
from itertools import count
|
|
|
|
|
|
|
2026-05-16 16:20:59 +00:00
|
|
|
|
from task2.strategyObjects.pathFindingStrategy import PathFindingStrategy
|
2026-05-20 18:23:47 +00:00
|
|
|
|
from task2.strategyObjects.util import restorePath
|
2026-05-16 16:20:59 +00:00
|
|
|
|
|
|
|
|
|
|
from task2.mazeObjects.maze import Maze
|
|
|
|
|
|
from task2.mazeObjects.cell import Cell
|
2026-05-23 09:02:30 +00:00
|
|
|
|
from task2.mazeObjects.path import Path
|
2026-05-16 16:20:59 +00:00
|
|
|
|
|
|
|
|
|
|
class AStar(PathFindingStrategy):
|
|
|
|
|
|
"""Алгоритм с эвристикой (etc. манхэттенское расстояние) – компромисс между скоростью и оптимальностью."""
|
2026-05-20 18:23:47 +00:00
|
|
|
|
def heuristic(self, first: Cell, second: Cell) -> int:
|
|
|
|
|
|
return abs(first.x - second.x) + abs(first.y - second.y)
|
|
|
|
|
|
|
2026-05-23 09:02:30 +00:00
|
|
|
|
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
|
2026-05-20 18:23:47 +00:00
|
|
|
|
tie_breaker = count()
|
|
|
|
|
|
start_heuristic = self.heuristic(start, exit)
|
|
|
|
|
|
heap: list[tuple[int, int, int, Cell]] = [
|
|
|
|
|
|
(start_heuristic, start_heuristic, next(tie_breaker), start)
|
|
|
|
|
|
]
|
|
|
|
|
|
g_score: dict[Cell, int] = {start: 0}
|
|
|
|
|
|
parents: dict[Cell, Cell | None] = {start: None}
|
|
|
|
|
|
visited: set[Cell] = set()
|
|
|
|
|
|
|
|
|
|
|
|
while heap:
|
|
|
|
|
|
_, _, _, current = heapq.heappop(heap)
|
|
|
|
|
|
if current in visited:
|
|
|
|
|
|
continue
|
|
|
|
|
|
visited.add(current)
|
|
|
|
|
|
|
2026-05-25 00:00:00 +00:00
|
|
|
|
if current.isExit:
|
2026-05-23 09:02:30 +00:00
|
|
|
|
return Path(restorePath(parents, exit), len(visited))
|
2026-05-20 18:23:47 +00:00
|
|
|
|
|
|
|
|
|
|
for neighbor in maze.getNeighbors(current):
|
|
|
|
|
|
tentative_score = g_score[current]
|
|
|
|
|
|
if tentative_score < g_score.get(neighbor, 10**12):
|
|
|
|
|
|
g_score[neighbor] = tentative_score
|
|
|
|
|
|
parents[neighbor] = current
|
|
|
|
|
|
heuristic = self.heuristic(neighbor, exit)
|
|
|
|
|
|
priority = tentative_score + heuristic
|
|
|
|
|
|
heapq.heappush(
|
|
|
|
|
|
heap,
|
|
|
|
|
|
(priority, heuristic, next(tie_breaker), neighbor),
|
|
|
|
|
|
)
|
2026-05-23 09:02:30 +00:00
|
|
|
|
return Path(None, len(visited))
|