import heapq from itertools import count from task2.strategyObjects.pathFindingStrategy import PathFindingStrategy from task2.strategyObjects.util import restorePath from task2.mazeObjects.maze import Maze from task2.mazeObjects.cell import Cell from task2.mazeObjects.path import Path class AStar(PathFindingStrategy): """Алгоритм с эвристикой (etc. манхэттенское расстояние) – компромисс между скоростью и оптимальностью.""" def heuristic(self, first: Cell, second: Cell) -> int: return abs(first.x - second.x) + abs(first.y - second.y) def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path: 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) if current.isExit: return Path(restorePath(parents, exit), len(visited)) 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), ) return Path(None, len(visited))