A*寻路基本概念和C++实现A*算法

前言

要先了解A*算法,得首先了解BFS——广度优先遍历

关于BFS

广度优先搜索(BFS)基本概念
算法基础:BFS和DFS的直观解释

关于A*

了解BFS之后,我们发现BFS不是很智能,BFS需要去遍历当前节点所有旁边的点,它是没有目标性的,像洪水一样,移动方向是四面八方。
我们想要把它变得更智能一点,也就是有目的性的去找终点。
这里就有一个启发函数

F = G + H

假设现在是从起点A终点B

  • G = 从起点A,沿着产生的路径,移动到网格上指定方格的移动耗费。
  • H = 从网格上那个方格移动到终点B的预估移动耗费。这经常被称为启发式的,可能会让你有点迷惑。这样叫的原因是因为它只是个猜测。我们没办法事先知道路径的长度,因为路上可能存在各种障碍(墙,水,等等)。虽然本文只提供了一种计算H的方法,但是你可以在网上找到很多其他的方法。(计算H的方法一般为:曼哈顿距离、欧几里得距离)

有了这个启发函数,那么就会让我们的寻路算法更加智能,因为它有了一个目标,往这个最终目标移动就行了。

具体可以看看这篇文章:A星(A*, A Star)算法详解.
这个是视频A*寻路算法详解 #A星 #启发式搜索

C++代码实现

#include <iostream>
#include <queue>
#include <map>
using namespace std;

typedef pair<int, int> pii;//(横坐标,纵坐标)
typedef pair<int, pii> piii;//(当前点的F值,pii)

int dx[4] = {
    
    0, 1, 0, -1}, dy[4] = {
    
    1, 0, -1, 0};//四个方向
const int N = 1e3 + 10;
int g[N][N];//地图
map<pii, int> g_costs;//当前点到起点的G值
map<pii, pii> parent;//记录当前节点的父节点,用于找到最终路径

//H值,我这里计算的是曼哈顿距离
int Get_H(int cur_x, int cur_y, int ed_x, int ed_y){
    
    
    return abs(ed_y - cur_y) + abs(ed_x - cur_x);
}

string Get_Path(pii st_point, pii ed_point){
    
    
    string path = "";
    pii cur_point = ed_point;
    while(cur_point != st_point){
    
    
        path += "(" + to_string(cur_point.first) + "," + to_string(cur_point.second) + ") <- ";
        cur_point = parent[cur_point];
    }
    path += "(" + to_string(cur_point.first) + "," + to_string(cur_point.second) + ")";
    return path;
}

int A_Star(int st_x, int st_y, int ed_x, int ed_y, int n, int m){
    
    
    priority_queue<piii, vector<piii>, greater<piii>> heap;
    heap.push({
    
    0, {
    
    st_x, st_y}});
    while(heap.size()){
    
    
        piii now = heap.top();
        heap.pop();
        pii point = now.second;
        if(point.first == ed_x && point.second == ed_y) return now.first;
        for(int i = 0; i < 4; i++){
    
    
            int nx = point.first + dx[i], ny = point.second + dy[i];
            int new_cost = g_costs[point] + 1;
            pii ne_point = {
    
    nx, ny};
            if(nx < 0 || nx >= n || ny < 0 || ny >= m || g[nx][ny] == 0) continue;
            if(parent.count(ne_point) == 0 || new_cost < g_costs[ne_point]){
    
    
                g_costs[ne_point] = new_cost;
                int f = new_cost + Get_H(nx, ny, ed_x, ed_y);
                heap.push({
    
    f, ne_point});
                parent[ne_point] = point;
            }
        }
    }
    return -1;
}

int main(){
    
    
    int n, m;
    int st_x, st_y, ed_x, ed_y;
    cin >> n >> m;
    for(int i = 0; i < n; i++){
    
    
        for(int j = 0; j < m; j++){
    
    
            cin >> g[i][j];
        }
    }
    cin >> st_x >> st_y >> ed_x >> ed_y;
    cout << "起点: (" << st_x << "," << st_y << ")\n";
    cout << "终点: (" << ed_x << "," << ed_y << ")\n";
    cout << "距离为" << A_Star(st_x, st_y, ed_x, ed_y, n, m) << "步" << '\n';
    cout << "具体路径为\n";
    cout << Get_Path({
    
    st_x, st_y}, {
    
    ed_x, ed_y});
    return 0;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_52855744/article/details/126268974