2024-01-01 20:12:48 +01:00
|
|
|
|
#ifndef _DIJKSTRA_HPP
|
|
|
|
|
#define _DIJKSTRA_HPP
|
|
|
|
|
|
2024-01-03 12:50:29 +01:00
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <cassert>
|
|
|
|
|
#include <functional>
|
|
|
|
|
#include <optional>
|
|
|
|
|
#include <utility>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
#include "graph.hpp"
|
|
|
|
|
|
|
|
|
|
auto dijkstra(const graph& g, const vertex_t& source)
|
|
|
|
|
-> std::vector<std::vector<int>> {
|
|
|
|
|
// make sure that ‹source› exists
|
|
|
|
|
assert(g.has(source));
|
|
|
|
|
|
|
|
|
|
// initialize the distances
|
|
|
|
|
std::vector<std::vector<int>> distances(
|
|
|
|
|
g.height(), std::vector(g.width(), graph::unreachable()));
|
|
|
|
|
|
|
|
|
|
// initialize the visited
|
|
|
|
|
std::vector<std::vector<bool>> visited(g.height(),
|
|
|
|
|
std::vector(g.width(), false));
|
|
|
|
|
|
|
|
|
|
// ‹source› destination denotes the beginning where the cost is 0
|
|
|
|
|
auto [sx, sy] = source;
|
|
|
|
|
distances[sy][sx] = 0;
|
|
|
|
|
|
|
|
|
|
pqueue_t priority_queue{std::make_pair(0, source)};
|
|
|
|
|
std::optional<pqueue_item_t> item{};
|
|
|
|
|
while ((item = popq(priority_queue))) {
|
|
|
|
|
auto [cost, u] = *item;
|
|
|
|
|
auto [x, y] = u;
|
|
|
|
|
|
|
|
|
|
// we have already found the shortest path
|
|
|
|
|
if (visited[y][x]) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
visited[y][x] = true;
|
|
|
|
|
|
|
|
|
|
for (const auto& [dx, dy] : DIRECTIONS) {
|
|
|
|
|
auto v = std::make_pair(x + dx, y + dy);
|
|
|
|
|
auto cost = g.cost(u, v);
|
|
|
|
|
|
|
|
|
|
// if we can move to the cell and it's better, relax¹ it and update queue
|
|
|
|
|
if (cost != graph::unreachable() &&
|
|
|
|
|
distances[y][x] + cost < distances[y + dy][x + dx]) {
|
|
|
|
|
distances[y + dy][x + dx] = distances[y][x] + cost;
|
|
|
|
|
pushq(priority_queue, std::make_pair(distances[y + dy][x + dx], v));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return distances;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-01 20:12:48 +01:00
|
|
|
|
#endif /* _DIJKSTRA_HPP */
|