A* algorithm is an informed search algorithm that finds the shortest path between two given nodes on a graph. It uses a heuristic function to estimate the cost of reaching the goal from the current node. A* algorithm is guaranteed to find the shortest path if the heuristic is admissible and consistent.
open_list
, closed_list
, g_score
, h_score
, and f_score
.open_list
with an initial g_score
of 0 and h_score
calculated using the heuristic function.open_list
is not empty, select the node with the lowest f_score
and remove it from open_list
.closed_list
.g_score
and h_score
using the heuristic function.closed_list
, skip it.open_list
, add it to the open_list
.open_list
and the tentative g_score
is greater than or equal to its current g_score
, skip it. Otherwise, update the g_score
, h_score
, and f_score
of the neighboring node and add it to the open_list
.open_list
is empty.import heapq
def heuristic(a, b):
return abs(b[0] - a[0]) + abs(b[1] - a[1])
def astar(array, start, goal):
neighbors = [(0,1),(0,-1),(1,0),(-1,0),(1,1),(1,-1),(-1,1),(-1,-1)]
close_set = set()
came_from = {}
gscore = {start:0}
fscore = {start:heuristic(start, goal)}
oheap = []
heapq.heappush(oheap, (fscore[start], start))
while oheap:
current = heapq.heappop(oheap)[1]
if current == goal:
data = []
while current in came_from:
data.append(current)
current = came_from[current]
return data
close_set.add(current)
for i, j in neighbors:
neighbor = current[0] + i, current[1] + j
tentative_g_score = gscore[current] + heuristic(current, neighbor)
if 0 <= neighbor[0] < array.shape[0]:
if 0 <= neighbor[1] < array.shape[1]:
if array[neighbor[0]][neighbor[1]] == 1:
continue
else:
continue
else:
continue
if neighbor in close_set and tentative_g_score >= gscore.get(neighbor, 0):
continue
if tentative_g_score < gscore.get(neighbor, 0) or neighbor not in [i[1]for i in oheap]:
came_from[neighbor] = current
gscore[neighbor] = tentative_g_score
fscore[neighbor] = tentative_g_score + heuristic(neighbor, goal)
heapq.heappush(oheap, (fscore[neighbor], neighbor))
return None
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
#include <utility>
#include <cmath>
#include <unordered_map>
#include <set>
using namespace std;
typedef pair<int, int> pii;
const int INF = 1e9;
int heuristic(pii a, pii b) {
return abs(b.first - a.first) + abs(b.second - a.second);
}
vector<pii> astar(vector<vector<int>>& grid, pii start, pii goal) {
int n = grid.size(), m = grid[0].size();
vector<pii> dirs = {{0,1}, {0,-1}, {1,0}, {-1,0}, {1,1}, {1,-1}, {-1,1}, {-1,-1}};
priority_queue<pii, vector<pii>, greater<pii>> pq;
unordered_map<int, unordered_map<int, int>> gscore;
unordered_map<int, unordered_map<int, int>> fscore;
unordered_map<int, unordered_map<int, pii>> came_from;
set<pii> closed_set;
gscore[start.first][start.second] = 0;
fscore[start.first][start.second] = heuristic(start, goal);
pq.push({fscore[start.first][start.second], (start.first << 16) | start.second});
while (!pq.empty()) {
auto curr = pq.top(); pq.pop();
int x = curr.second >> 16, y = curr.second & 0xFFFF;
if (make_pair(x, y) == goal) {
vector<pii> path;
while (x != start.first || y != start.second) {
path.push_back({x, y});
int tmp_x = x, tmp_y = y;
x = came_from[tmp_x][tmp_y].first;
y = came_from[tmp_x][tmp_y].second;
}
path.push_back({x, y});
reverse(path.begin(), path.end());
return path;
}
closed_set.insert({x, y});
for (auto dir : dirs) {
int nx = x + dir.first, ny = y + dir.second;
if (nx < 0 || nx >= n || ny < 0 || ny >= m || grid[nx][ny] == 1) continue;
if (closed_set.count({nx, ny})) continue;
int tentative_gscore = gscore[x][y] + heuristic({x, y}, {nx, ny});
if (!gscore.count(nx) || !gscore[nx].count(ny) || tentative_gscore < gscore[nx][ny]) {
came_from[nx][ny] = {x, y};
gscore[nx][ny] = tentative_gscore;
fscore[nx][ny] = tentative_gscore + heuristic({nx, ny}, goal);
pq.push({fscore[nx][ny], (nx << 16) | ny});
}
}
}
return {};
}
int main() {
vector<vector<int>> grid = {
{0, 0, 0, 0, 0},
{0, 1, 1, 1, 0},
{0, 1, 0, 0, 0},
{0, 1, 0, 1, 0},
{0, 0, 0, 1, 0}
};
pii start = {0, 0}, goal = {4, 4};
auto path = astar(grid, start, goal);
for (auto p : path) {
cout << "(" << p.first << ", " << p.second << ") ";
}
cout << endl;
return 0;
}