Алгоритмы Дейкстры и A*: поиск кратчайшего пути
Как найти самый быстрый путь на карте? Как ИИ в игре находит путь до цели, обходя стены?
Ответ — в алгоритмах поиска кратчайшего пути. Сегодня разберём два самых популярных:

---
Что решают эти алгоритмы
И Дейкстра, и A* ищут путь из точки A в точку B по графу, где:
- Вершины — узлы (например, перекрёстки, клетки карты, точки маршрута)
- Рёбра — связи между ними с весами (расстояние, время, цена и т.д.)
Они гарантируют самый дешёвый путь, если веса неотрицательные.
---
Алгоритм Дейкстры (Dijkstra)
Простой и надёжный: на каждом шаге выбираем узел с минимальной стоимостью и обновляем соседей.
- Не использует эвристик
- Работает во всех графах без отрицательных весов
- Может найти все кратчайшие пути от одной вершины

Python:
import heapq
def dijkstra(graph, start):
dist = {v: float('inf') for v in graph}
dist[start] = 0
queue = [(0, start)]
while queue:
cost, u = heapq.heappop(queue)
if cost > dist[u]:
continue
for v, weight in graph[u]:
alt = dist[u] + weight
if alt < dist[v]:
dist[v] = alt
heapq.heappush(queue, (alt, v))
return dist

Python:
graph = {
'A': [('B', 1), ('C', 4)],
'B': [('C', 2), ('D', 5)],
'C': [('D', 1)],
'D': []
}
Код на Си:
C:
#include <stdio.h>
#include <limits.h>
#define V 4 // количество вершин
int min_distance(int dist[], int visited[]) {
int min = INT_MAX, index = -1;
for (int i = 0; i < V; i++) {
if (!visited[i] && dist[i] < min) {
min = dist[i];
index = i;
}
}
return index;
}
void dijkstra(int graph[V][V], int start) {
int dist[V];
int visited[V] = {0};
for (int i = 0; i < V; i++)
dist[i] = INT_MAX;
dist[start] = 0;
for (int count = 0; count < V - 1; count++) {
int u = min_distance(dist, visited);
visited[u] = 1;
for (int v = 0; v < V; v++) {
if (!visited[v] && graph[u][v] && dist[u] != INT_MAX &&
dist[u] + graph[u][v] < dist[v])
{
dist[v] = dist[u] + graph[u][v];
}
}
}
printf("Кратчайшие расстояния от вершины %d:\n", start);
for (int i = 0; i < V; i++)
printf("До %d = %d\n", i, dist[i]);
}
int main() {
// Матрица смежности (веса)
int graph[V][V] = {
{0, 1, 4, 0},
{0, 0, 2, 5},
{0, 0, 0, 1},
{0, 0, 0, 0}
};
dijkstra(graph, 0); // из вершины 0
return 0;
}
---
Алгоритм A* (A-star)
Это оптимизированная версия Дейкстры с «подсказками».
Он использует эвристику — оценку расстояния до цели.
Что такое эвристика в A*
Эвристика — это оценка оставшегося расстояния от текущей вершины до цели.Она помогает A* "предугадывать", где находится цель, и двигаться более умно, чем Дейкстра.

Код:
f(n) = g(n) + h(n)
g(n)
— расстояние от старта доn
(как у Дейкстры)h(n)
— приближённая оценка отn
до цели (например, Евклидово или Manhattan-расстояние)


Python:
import heapq
def a_star(graph, start, goal, heuristic):
open_set = [(0, start)]
g = {start: 0}
came_from = {}
while open_set:
_, current = heapq.heappop(open_set)
if current == goal:
break
for neighbor, cost in graph[current]:
tentative_g = g[current] + cost
if neighbor not in g or tentative_g < g[neighbor]:
g[neighbor] = tentative_g
f = tentative_g + heuristic(neighbor, goal)
heapq.heappush(open_set, (f, neighbor))
came_from[neighbor] = current
return g.get(goal, float('inf'))

Что происходит по шагам:
- g[n] — стоимость пути от старта до узла n (накапливаем её)
- heuristic(n, goal) — оценка до цели
- f = g + h — итоговая "стоимость" маршрута
- Используется heapq — приоритетная очередь, которая выбирает вершину с наименьшим f
Python:
def manhattan(node, goal):
x1, y1 = node
x2, y2 = goal
return abs(x1 - x2) + abs(y1 - y2)
Как вызывать:
Python:
res = a_star(graph, 'A', 'D', manhattan)
print("Минимальное расстояние A → D:", res)
Пример на Си, ориентирован на поле 5×5, где можно двигаться по 4 направлениям (вверх, вниз, влево, вправо), а 1 — проходимо, 0 — препятствие.
Код:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#define N 5
typedef struct {
int x, y;
int g; // стоимость от старта
int f; // общая стоимость (g + h)
} Node;
int goal_x = 4, goal_y = 4;
int heuristic(int x, int y) {
return abs(goal_x - x) + abs(goal_y - y); // Манхэттен
}
int in_bounds(int x, int y) {
return x >= 0 && x < N && y >= 0 && y < N;
}
int is_passable(int grid[N][N], int x, int y) {
return grid[x][y] == 1;
}
// простая очередь с приоритетом (по f)
void push(Node* open[], int* size, Node* n) {
int i = *size;
while (i > 0 && open[i - 1]->f > n->f) {
open[i] = open[i - 1];
i--;
}
open[i] = n;
(*size)++;
}
Node* pop(Node* open[], int* size) {
return open[--(*size)];
}
void a_star(int grid[N][N], int start_x, int start_y) {
int closed[N][N] = {0};
int came_from[N][N][2];
Node* open[100];
int open_size = 0;
Node* start = malloc(sizeof(Node));
start->x = start_x;
start->y = start_y;
start->g = 0;
start->f = heuristic(start_x, start_y);
push(open, &open_size, start);
int dirs[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
while (open_size > 0) {
Node* current = pop(open, &open_size);
if (current->x == goal_x && current->y == goal_y) {
printf("Путь найден:\n");
int x = goal_x, y = goal_y;
while (!(x == start_x && y == start_y)) {
printf("(%d, %d) <- ", x, y);
int px = came_from[x][y][0];
int py = came_from[x][y][1];
x = px;
y = py;
}
printf("(%d, %d)\n", start_x, start_y);
return;
}
closed[current->x][current->y] = 1;
for (int i = 0; i < 4; i++) {
int nx = current->x + dirs[i][0];
int ny = current->y + dirs[i][1];
if (!in_bounds(nx, ny) || !is_passable(grid, nx, ny) || closed[nx][ny])
continue;
int new_g = current->g + 1;
Node* neighbor = malloc(sizeof(Node));
neighbor->x = nx;
neighbor->y = ny;
neighbor->g = new_g;
neighbor->f = new_g + heuristic(nx, ny);
came_from[nx][ny][0] = current->x;
came_from[nx][ny][1] = current->y;
push(open, &open_size, neighbor);
}
}
printf("Путь не найден.\n");
}
Использование:
C:
int main() {
int grid[N][N] = {
{1, 1, 1, 1, 1},
{0, 0, 0, 1, 0},
{1, 1, 1, 1, 1},
{1, 0, 0, 0, 1},
{1, 1, 1, 1, 1}
};
a_star(grid, 0, 0);
return 0;
}
---
Сравнение: Дейкстра vs A*
Критерий | Дейкстра | A* |
---|---|---|
Эвристика | Нет | Да |
Оптимальность | Гарантирована | Если эвристика допустима |
Скорость | Медленнее | Быстрее на практике |
Подходит для | Все кратчайшие пути | Целевой путь (start → goal) |
Гарантирует точный путь | Да | Да (если h не переоценивает) |
---
Где применяются?

- Маршруты в GPS (все пути из одной точки)
- Планирование в графах без эвристик
- Сети и маршрутизаторы

- Искусственный интеллект в играх
- Роботы и дроны (путь от A до B)
- Динамическая навигация
Вывод
Алгоритмы поиска кратчайшего пути — основа навигации, планирования, анализа маршрутов.
- Дейкстра — надёжен, универсален
- A\* — быстрее, если есть эвристика

