aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-10-24 20:46:43 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-10-24 20:46:43 +0200
commitdabfb8188aab86ea8d8c9794ee8e46f6e22291f4 (patch)
tree492f8139c36aa8dc117a7c0de9162a89501c1d84
parent2502246d8b08e8660dd08e2c2089c2ef2cf3458b (diff)
fix dijkstra but efficient this time
-rw-r--r--DijkstraPathfinder.cpp69
-rw-r--r--DijkstraPathfinder.h5
2 files changed, 46 insertions, 28 deletions
diff --git a/DijkstraPathfinder.cpp b/DijkstraPathfinder.cpp
index 2fb07f5..8d86235 100644
--- a/DijkstraPathfinder.cpp
+++ b/DijkstraPathfinder.cpp
@@ -1,4 +1,5 @@
#include <algorithm>
+#include <queue>
#include "DijkstraPathfinder.h"
#include "Museum.h"
@@ -38,42 +39,54 @@ DijkstraPathfinder::Node & DijkstraPathfinder::map_get(const XY & pos) {
return this->map[pos];
}
-void DijkstraPathfinder::dijkstra(const XY & here) {
- this->set_visited(here);
+void DijkstraPathfinder::dijkstra(const XY & start) {
PathfindingContext & ctx = this->museum.pathfinding;
- unsigned int dist_end = this->map_get(this->end).distance;
- vector<pair<unsigned int, XY>> neighbors;
- vector<XY> offsets = {
+ const vector<XY> offsets = {
{ 0, 1 },
{ 1, 0 },
{ 0, -1 },
{ -1, 0 },
};
- for (const XY & offset : offsets) {
- const XY neighbor = here + offset;
- if (ctx.empty_point(neighbor)) continue;
-
- Tile & neighbor_tile = this->museum.canvas.get_tile(neighbor);
- unsigned int neighbor_cost = ctx.get_weight(neighbor_tile.data.type);
- unsigned int dist_neighbor = this->map_get(here).distance + neighbor_cost;
-
- if (dist_neighbor >= dist_end) continue;
-
- Node & neighbor_node = this->map_get(neighbor);
- if (dist_neighbor >= neighbor_node.distance) continue;
-
- neighbor_node.parent = here;
- neighbor_node.distance = dist_neighbor;
- neighbors.push_back({ dist_neighbor, neighbor });
- }
- // sort by cost ascending
- sort(neighbors.begin(), neighbors.end(), [] (auto & left, auto & right) {
- return left.first < right.first;
- });
- for (pair<unsigned int, XY> & neighbor : neighbors) {
- this->dijkstra(neighbor.second);
+ auto compare = [] (Neighbor a, Neighbor b) -> bool { return a.distance > b.distance; };
+ priority_queue<Neighbor, vector<Neighbor>, decltype(compare)> pq;
+
+ pq.push({ 0, start });
+ this->map_get(start).distance = 0;
+
+ while (!pq.empty()) {
+ XY here = pq.top().position;
+ unsigned int distance = pq.top().distance;
+ pq.pop();
+
+ if (this->is_visited(here)) continue;
+ this->set_visited(here);
+
+ if (distance > this->map_get(here).distance) continue;
+
+ unsigned int dist_end = this->map_get(this->end).distance;
+
+ for (const XY & offset : offsets) {
+ const XY neighbor = here + offset;
+ if (ctx.empty_point(neighbor)) continue;
+
+ Tile & neighbor_tile = this->museum.canvas.get_tile(neighbor);
+ unsigned int dist_neighbor = distance + ctx.get_weight(neighbor_tile.data.type);
+
+ if (dist_neighbor >= dist_end) continue;
+
+ Node & neighbor_node = this->map_get(neighbor);
+ if (dist_neighbor >= neighbor_node.distance) continue;
+
+ neighbor_node.parent = here;
+ neighbor_node.distance = dist_neighbor;
+
+ pq.push({
+ .distance = dist_neighbor,
+ .position = neighbor,
+ });
+ }
}
}
diff --git a/DijkstraPathfinder.h b/DijkstraPathfinder.h
index eddb26f..5fb1e21 100644
--- a/DijkstraPathfinder.h
+++ b/DijkstraPathfinder.h
@@ -22,6 +22,11 @@ private:
unsigned int distance = -1;
XY parent;
};
+ struct Neighbor {
+ unsigned int distance = -1;
+ XY position;
+ };
+
Node & map_get(const XY &);
std::unordered_map<XY, Node> map;