магазин Лувр

Как с помощью волнового алгоритма найти кратчайший путь C++

Волновой алгоритм (также известный как алгоритм Ли) - это эффективный способ нахождения кратчайшего пути в графе или сетке от одной точки к другой. Он основан на принципе распространения волн от начальной точки до конечной. Этот алгоритм широко применяется в различных областях, таких как робототехника, игровая разработка, географические информационные системы и даже в биоинформатике.

Основные шаги алгоритма

  1. Создайте сетку или граф, в котором требуется найти кратчайший путь. Каждое поле сетки должно иметь значение, которое указывает, доступно оно или нет.
  2. Установите начальную точку и конечную точку для поиска кратчайшего пути.
  3. Инициализируйте волну в начальной точке сетки, присвоив ей значение "0". Остальные точки сетки должны быть помечены как недоступные или иметь бесконечное значение.
  4. Повторите следующие шаги до тех пор, пока волна не достигнет конечной точки:
    • Распространите волну от текущего положения на одну клетку во все доступные соседние клетки.
    • Увеличьте значение текущей волны на 1.
    • Обновите значения доступных клеток с минимальным значением волны.
  5. Когда волна достигнет конечной точки, значит путь найден.
  6. Восстановите кратчайший путь, путем следования обратно по значению волны от конечной точки до начальной. В результате вы получите кратчайший путь.

Реализация на C++

Ниже приведен пример кода, демонстрирующий реализацию волнового алгоритма для поиска кратчайшего пути в сетке с использованием языка C++:

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

// Структура для хранения состояния клетки сетки
struct State {
    int x, y, wave;

    State(int x, int y, int wave) : x(x), y(y), wave(wave) {}
};

// Функция для проверки, является ли клетка сетки доступной
bool isAccessible(int x, int y, vector<vector<int>>& grid) {
    int rows = grid.size();
    int cols = grid[0].size();

    if (x >= 0 && x < rows && y >= 0 && y < cols && grid[x][y] == 0) {
        return true;
    }
    return false;
}

// Функция для нахождения кратчайшего пути с использованием волнового алгоритма
vector<pair<int, int>> findShortestPath(vector<vector<int>>& grid, pair<int, int> start, pair<int, int> end) {
    queue<State> q;
    vector<vector<bool>> visited(grid.size(), vector<bool>(grid[0].size(), false));
    vector<pair<int, int>> directions{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    vector<pair<int, int>> path;

    // Инициализация волны в начальной точке
    q.push(State(start.first, start.second, 0));
    visited[start.first][start.second] = true;

    while (!q.empty()) {
        State current = q.front();
        q.pop();

        if (current.x == end.first && current.y == end.second) {
            // Конечная точка достигнута, восстановление пути
            int x = current.x;
            int y = current.y;
            int wave = current.wave;

            while (wave != 0) {
                for (auto direction : directions) {
                    int newX = x + direction.first;
                    int newY = y + direction.second;

                    if (isAccessible(newX, newY, grid) && visited[newX][newY]) {
                        x = newX;
                        y = newY;
                        wave--;
                        path.push_back({x, y});
                        break;
                    }
                }
            }
            break;
        }

        // Распространение волны на соседние клетки
        for (auto direction : directions) {
            int newX = current.x + direction.first;
            int newY = current.y + direction.second;

            if (isAccessible(newX, newY, grid) && !visited[newX][newY]) {
                q.push(State(newX, newY, current.wave + 1));
                visited[newX][newY] = true;
            }
        }
    }

    reverse(path.begin(), path.end());
    return path;
}

// Пример использования
int main() {
    vector<vector<int>> grid = {
        {0, 0, 1, 0, 0, 0},
        {0, 0, 1, 0, 1, 0},
        {0, 0, 0, 0, 1, 0},
        {0, 1, 1, 1, 0, 0},
        {0, 0, 0, 0, 0, 0},
    };

    pair<int, int> start = {0, 0};
    pair<int, int> end = {4, 5};

    vector<pair<int, int>> shortestPath = findShortestPath(grid, start, end);

    cout << "Кратчайший путь:" << endl;
    for (auto cell : shortestPath) {
        cout << "(" << cell.first << ", " << cell.second << ")" << endl;
    }

    return 0;
}

Этот пример кода демонстрирует использование волнового алгоритма для поиска кратчайшего пути в сетке. Его выход будет содержать точки, образующие этот путь. Этот пример можно модифицировать для работы с сетками различного размера или использовать для других типов графов.

Волновой алгоритм является мощным инструментом для нахождения кратчайших путей в графах или сетках. Он использует простой и интуитивно понятный подход, делая его широко применимым в реальных задачах. Познакомьтесь с этим алгоритмом и примените его в своих проектах для поиска оптимальных путей.