A* е набор от стъпки (алгоритъм), който компютрите използват, за да намерят най-краткия или най-евтиния път между две места в граф (набор от възли и връзки между тях). Ако имате списък с места и колко струва (или колко време отнема) да се премине директно от едно място до друго, A* може бързо да открие най-добрия маршрут. Алгоритъмът е свързан с алгоритъма на Дийкстра — в общия случай, когато евристиката е нула, A* става еквивалентен на Дийкстра — но A* прави „интелигентни предположения“ (евристика), за да не разглежда ненужно много пътища. Това е подходящ метод, ако искате един добър път между две точки. Ако трябва да намерите много пътища за всички двойки възли в една и съща карта, има алгоритми като Флойд–Уоршал, които могат да са по-ефективни за тази задача. A* не е подходящ за задачи като задачата за пътуващия търговец, където трябва да посетите много места в едно пътуване.

Как работи A*

Основната идея на A* е да комбинира вече изминатия разход и оценката за оставащия разстояние, за да приоритизира кои възли да се изследват първо. За всеки възел алгоритъмът поддържа три стойности:

  • g(n) — реалния разход от началния възел до възел n (колко струва вече пътят до тук);
  • h(n) — евристична оценка за разхода от n до целта (оценка на оставащото разстояние);
  • f(n) = g(n) + h(n) — оценка за общия разход през възел n.

Алгоритъмът използва две множества: open (възли, които предстои да се разгледат, обикновено реализирано като приоритетна опашка по f) и closed (възли, които вече са разгледани). Всяка стъпка A* вади от open възела с най-ниско f, разглежда съседите му и актуализира техните g/h/f стойности, докато не достигне целта.

Евристика (h)

Евристиката е важна за бързината и коректността на A*:

  • Адмисибилна евристика: никога не надценява истинския минимален разход до целта. Ако h е адмисибилна, A* гарантира, че ще намери оптимален (най-кратък) път.
  • Конзистентна (монотонна) евристика: за всяко ребро (n → m) важи h(n) ≤ cost(n,m) + h(m). Конзистентността гарантира, че f-стойността на възлите не намалява при разширяване и позволява проста реализация без повторни вмъквания в open.
  • Примери за евристики в равнинни мрежи: Манхатънско разстояние (за движение само по вертикал/хоризонтал), Евклидово разстояние (за движение в произволна посока), Чебишев (за движение и по диагонал с еднаква цена).

Свойства и сложност

  • Оптималност: Ако евристиката е адмисибилна (и особено ако е и конзистентна), A* намира оптимален път.
  • Пълнота: A* е пълен при крайни графи и положителни ребърни тежести — ще намери път, ако такъв съществува.
  • Времева и пространствена сложност: в най-лошия случай може да бъде експоненална по дълбочина/размер на графа, но в практиката — и с добра евристика — е много по-бърз от неевристични търсения като Дийкстра.

Основни стъпки (псевдокод като последователност)

  • Постави началния възел в open с g(start)=0 и f=start.h.
  • Докато open не е празно:
    • Вземи възела current от open с най-ниско f.
    • Ако current е целта → възстанови пътя чрез проследяване назад и приключи.
    • Премести current в closed.
    • За всеки съсед neighbor на current:
      • Изчисли tentative_g = g(current) + cost(current, neighbor).
      • Ако neighbor е в closed и tentative_g ≥ g(neighbor) → пропусни.
      • Ако neighbor не е в open или tentative_g < g(neighbor):
        • Актуализирай g(neighbor) = tentative_g, запази parent pointer към current, и пресметни f = g + h.
        • Ако neighbor не е в open → вмъкни го в open.

Практически съвети за имплементация

  • Използвайте ефективна приоритетна опашка (heap) за open; за поддръжка на актуализации може да е полезна структура, която поддържа намаление на ключ (decrease-key) или запис на записи с версия/идентификатор.
  • Поддържайте parent (предходник) за всеки възел, за да може да възстановите пътя при достигане на целта.
  • За големи карти помислете за варианти като итеративен дълбочинен A* (IDA*), Jump Point Search (за решетки) или предварително изчислени навигационни мрежи, за да намалите паметните и временни разходи.
  • В реални приложения често се използват и практични оптимизации: ограничение на обхвата, използване на евристики, комбиниране с водещи алгоритми за предварително маршрутизиране и др.

Къде се използва A*

  • Видео игри и симулации — за навигация на герои и NPC.
  • Роботика и автономни превозни средства — за планиране на траектории.
  • Географски информационни системи (карти и навигация).
  • Всички задачи, където трябва бързо да се намери един най-добър път между две точки при познати преходни разходи.

Разширения и варианти

  • Weighted A* — използва f = g + w·h (w > 1) за по-бързи, но евентуално ненапълно оптимални решения.
  • IDA* — итеративно задълбочаване, което намалява паметните изисквания.
  • Theta* и други алгоритми — търсят по-гладки или по-кратки траектории в непрекъснати пространства.

A* е много практичен и гъвкав инструмент за търсене на кратки пътища. С правилно избрана евристика и подходяща структура за данни той често намира оптималния маршрут много по-бързо от класическото безевристично търсене.