1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
| #include <vector> #include <queue> #include <cmath> #include <limits> #include <unordered_map>
using namespace std;
enum class Heuristic { MANHATTAN, EUCLIDEAN, CHEBYSHEV };
struct Point { int x, y; Point(int _x, int _y) : x(_x), y(_y) {} bool operator==(const Point& other) const { return x == other.x && y == other.y; } };
struct Node { Point pos; int g, h; Node* parent; Node(Point p, int g_cost, int h_cost, Node* parent_node) : pos(p), g(g_cost), h(h_cost), parent(parent_node) {} int f() const { return g + h; } bool operator<(const Node& other) const { return f() > other.f(); } };
class JPS { public: JPS(vector<vector<int>>& grid) : grid(grid) {} vector<Point> findPath(Point start, Point end, Heuristic heuristic) { if (grid[end.x][end.y] == 1) return {}; priority_queue<Node> openList; unordered_map<Point, Node*, PointHash> closed; Node* startNode = new Node(start, 0, calculateHeuristic(start, end, heuristic), nullptr); openList.push(*startNode); while (!openList.empty()) { Node current = openList.top(); openList.pop(); if (current.pos == end) { return reconstructPath(current); } closed[Point(current.pos.x, current.pos.y)] = ¤t; for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { if (dx == 0 && dy == 0) continue; Point jumpPos(current.pos.x + dx, current.pos.y + dy); if (isValid(jumpPos) && grid[jumpPos.x][jumpPos.y] != 1) { Point jumpResult = jump(jumpPos, dx, dy, end); if (jumpResult != Point(-1, -1)) { Node* neighbor = new Node(jumpResult, current.g + 1, calculateHeuristic(jumpResult, end, heuristic), ¤t); if (!contains(closed, neighbor->pos)) { openList.push(*neighbor); } } } } } } return {}; } private: vector<vector<int>> grid; struct PointHash { size_t operator()(const Point& p) const { return p.x * 1000000 + p.y; } }; bool isValid(Point p) { return p.x >= 0 && p.x < grid.size() && p.y >= 0 && p.y < grid[0].size(); } Point jump(Point p, int dx, int dy, Point end) { if (p == end) return p; if (!isValid(p) || grid[p.x][p.y] == 1) return Point(-1, -1); if (dx != 0 && dy != 0) { if ((grid[p.x - dx][p.y] == 1) || (grid[p.x][p.y - dy] == 1)) { return p; } } if (dx != 0 && dy != 0) { if ((grid[p.x - dx][p.y + dy] == 1) || (grid[p.x + dx][p.y - dy] == 1)) { return p; } } if (dx != 0 && dy == 0) { if ((grid[p.x + dx][p.y + 1] == 1) || (grid[p.x + dx][p.y - 1] == 1)) { return p; } return jump(Point(p.x + dx, p.y), dx, dy, end); } else if (dy != 0 && dx == 0) { if ((grid[p.x + 1][p.y + dy] == 1) || (grid[p.x - 1][p.y + dy] == 1)) { return p; } return jump(Point(p.x, p.y + dy), dx, dy, end); } else { return jump(Point(p.x + dx, p.y + dy), dx, dy, end); } } int calculateHeuristic(Point a, Point b, Heuristic h) { int dx = abs(a.x - b.x); int dy = abs(a.y - b.y); switch (h) { case Heuristic::MANHATTAN: return dx + dy; case Heuristic::EUCLIDEAN: return static_cast<int>(sqrt(dx*dx + dy*dy)); case Heuristic::CHEBYSHEV: return max(dx, dy); default: return 0; } } vector<Point> reconstructPath(Node& node) { vector<Point> path; Node* current = &node; while (current != nullptr) { path.push_back(current->pos); current = current->parent; } reverse(path.begin(), path.end()); return path; } bool contains(unordered_map<Point, Node*, PointHash>& map, Point key) { return map.find(key) != map.end(); } };
|