首页 > 编程语言 >A*算法C/C++实现

A*算法C/C++实现

时间:2024-08-25 17:22:39浏览次数:8  
标签:std Point 实现 C++ current 算法 启发式 节点

A*算法是一种在图形平面上,有多个节点的路径中,寻找一条从起始点(source)到目标点(goal)的最短遍历路径的算法。它属于启发式搜索算法,因为它使用启发式方法来计算图中的节点,从而减少实际计算的节点数量。

A*(A星)算法是一种启发式搜索算法,用于在图中找到从起始点(source)到目标点(goal)的最短路径。它属于最佳优先搜索算法的一种,使用启发式方法来估计从当前节点到目标节点的距离,以此来优化搜索过程。

算法原理

A*算法的核心思想是,它在搜索过程中,对每个节点计算两个值:

1. g(n):从起始点到当前节点n的实际代价。
2. h(n):从当前节点n到目标点的估计代价(启发式函数)。

算法使用这两个值的和(f(n) = g(n) + h(n))来评估每个节点的优先级。节点的f(n)值越小,被优先搜索的可能性越大。

启发式函数(Heuristic Function)

启发式函数h(n)是A*算法的关键部分,它必须满足以下条件:

- 一致性(或称为单调性):对于任意节点n,h(n)的值不能超过从n到目标点的实际最小代价。一致性保证了算法的最优性。
- 可接受性:h(n)的值不能为负。

常见的启发式函数包括:

- 曼哈顿距离:在网格地图中,当只能沿着水平或垂直方向移动时,从一点到另一点的最短路径长度。
- 欧几里得距离:直线距离,即两点之间的直线最短距离。
- 切比雪夫距离:在网格地图中,从一个点到另一个点的最短路径,允许对角线移动。

算法步骤

1. 初始化:将起始点加入开放列表(Open List),并设置其g(n)和h(n)值为0。
2. 循环:当开放列表非空时,执行以下步骤:
   - 从开放列表中取出f(n)值最小的节点n。
   - 如果n是目标点,则路径已经找到,可以停止搜索。
   - 否则,将n从开放列表移至关闭列表(Closed List),并遍历n的所有邻居节点:
     - 如果邻居节点已经在关闭列表中,忽略它。
     - 如果邻居节点不在开放列表中,将其添加到开放列表,并计算它的g(n)和h(n)值。
     - 如果邻居节点已在开放列表中,检查通过n到达该邻居节点是否更优(即g(n)值更小),如果是,则更新它的g(n)值和父节点。
3. 结束:如果开放列表为空,表示无法到达目标点。

特点

- 性能:A*算法的性能取决于启发式函数的选择。好的启发式函数可以显著减少搜索空间,提高效率。
- 最优性:如果启发式函数是一致的,A*算法可以保证找到最短路径。
- 适用性:A*算法适用于各种类型的图搜索问题,包括路径规划、游戏AI、机器人导航等领域。

A*算法是一种非常强大且灵活的算法,通过调整启发式函数,可以适应不同的应用场景。


 以下是A*算法的一个基本的C/C++实现示例。这个示例不包括特定的数据结构,如优先队列,你可能需要根据你的具体需求来实现或使用现有的库。

#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <cmath>
#include <algorithm>

// 定义点的结构
struct Point {
    int x, y;
};

// 定义优先队列中的元素,包含点、成本、启发式估计和父节点
struct Node {
    Point pt;
    double cost;
    double heuristic;
    Node* parent;

    Node(Point pt, double cost, double heuristic, Node* parent) :
        pt(pt), cost(cost), heuristic(heuristic), parent(parent) {}

    // 优先队列需要比较操作,这里定义一个比较函数
    bool operator>(const Node& other) const {
        return cost + heuristic > other.cost + other.heuristic;
    }
};

// 定义优先队列
typedef std::priority_queue<Node, std::vector<Node>, std::greater<Node>> PriorityQueue;

// 定义启发式函数,这里使用曼哈顿距离
double heuristic(const Point& a, const Point& b) {
    return std::abs(a.x - b.x) + std::abs(a.y - b.y);
}

// A*算法实现
std::vector<Point> aStarSearch(Point start, Point end, std::unordered_map<Point, std::vector<Point>> graph) {
    PriorityQueue pq;
    std::unordered_map<Point, double> costSoFar;
    std::unordered_map<Point, bool> visited;

    pq.push(Node(start, 0.0, heuristic(start, end), nullptr));
    costSoFar[start] = 0;
    visited[start] = false;

    while (!pq.empty()) {
        Node current = pq.top();
        pq.pop();

        if (current.pt == end) {
            // 找到终点,回溯路径
            std::vector<Point> path;
            while (current.parent) {
                path.push_back(current.pt);
                current = *current.parent;
            }
            std::reverse(path.begin(), path.end());
            return path;
        }

        if (visited[current.pt]) continue;
        visited[current.pt] = true;

        for (Point neighbor : graph[current.pt]) {
            if (visited[neighbor]) continue;

            double newCost = current.cost + 1; // 假设每步成本为1
            double heuristicCost = heuristic(neighbor, end);

            if (costSoFar.find(neighbor) == costSoFar.end() || newCost < costSoFar[neighbor]) {
                costSoFar[neighbor] = newCost;
                pq.push(Node(neighbor, newCost, heuristicCost, new current));
            }
        }
    }

    return std::vector<Point>(); // 没有找到路径
}

int main() {
    Point start = {0, 0};
    Point end = {10, 10};

    // 构建图,这里简单使用二维网格的四个邻居
    std::unordered_map<Point, std::vector<Point>> graph;
    for (int x = 0; x <= 10; ++x) {
        for (int y = 0; y <= 10; ++y) {
            Point pt = {x, y};
            graph[pt] = { {x-1, y}, {x+1, y}, {x, y-1}, {x, y+1} };
        }
    }

    std::vector<Point> path = aStarSearch(start, end, graph);
    for (const Point& pt : path) {
        std::cout << "(" << pt.x << ", " << pt.y << ")" << std::endl;
    }

    return 0;
}

这个代码示例提供了A*算法的基本框架,包括启发式函数、优先队列和搜索逻辑。你需要根据你的具体应用场景来调整图的表示和启发式函数。此外,你可能还需要考虑如何处理障碍物和不同的移动成本。

标签:std,Point,实现,C++,current,算法,启发式,节点
From: https://blog.csdn.net/2401_86771711/article/details/141465194

相关文章

  • 龙格-库塔法(Matlab实现)
    四阶龙格-库塔法介绍在各种龙格-库塔法当中有一个方法十分常用,以至于经常被称为“RK4”或者就是“龙格-库塔法”。该方法主要是在已知方程导数和初始值时,利用计算机的仿真应用,省去求解微分方程的复杂过程。令初值问题表述如下:则,对于该问题的RK4由如下方程给出:其中:这样,下......
  • Selenium实现元素定位
    Selenium提供了定位元素的方法find_element(),该方法被定义在WebDriver类中。一、参数1、两个参数,参数1根据不同定位方法确定,定位方法如下:(1)通过id定位:使用参数By.ID定位元素的ID属性;(2)通过元素名定位:使用参数By.NAME定位元素的NAME属性;(3)通过标签名定位:使用参数BY.TAG_NAME定位......
  • 信息学奥赛初赛天天练-75-NOIP2016普及组-完善程序-二分答案、二分查找、贪心算法、贪
    1完善程序(单选题,每小题3分,共30分)郊游活动有n名同学参加学校组织的郊游活动,已知学校给这n名同学的郊游总经费为A元,与此同时第i位同学自己携带了Mi元。为了方便郊游,活动地点提供B(≥n)辆自行车供人租用,租用第j辆自行车的价格为Cj元,每位同学可以使用自己携带的钱或......
  • springboot整合rabbitmq实现延迟队列
     一、rabbitmq安装使用dicker进行安装,点击查看 二、引入maven依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId><version>2.5.15</version></dependency>......
  • 代码随想录DAY24 - 回溯算法 - 08/23
    目录分割回文串题干思路和代码递归法复原IP地址题干思路和代码子集(非重复)题干思路和代码方法一:修改子集大小方法二:收集树的每个节点子集Ⅱ(含重复)题干思路和代码方法一:先去重,记录每个元素重复的次数方法二:先排序,再树层去重使用unordered_set对树层去重......
  • 代码随想录DAY25 - 回溯算法 - 08/24
    目录非递减子序列题干思路和代码递归法递归优化全排列题干思路和代码递归法全排列Ⅱ题干思路和代码方法一:用集合set去重方法二:先排序,再用数组去重非递减子序列题干题目:给你一个整数数组nums,找出并返回所有该数组中不同的递增子序列,递增子序列中至少有......
  • 【C++PCL】点云处理贪婪三角化曲面重建
    作者:迅卓科技简介:本人从事过多项点云项目,并且负责的项目均已得到好评!公众号:迅卓科技,一个可以让您可以学习点云的好地方重点:每个模块都有参数如何调试的讲解,即调试某个参数对结果的影响是什么,大家有问题可以评论哈,如果文章有错误的地方,欢迎来指出错误的地方。目录   ......
  • 算法笔记|Day34动态规划VII
    算法笔记|Day34动态规划VII☆☆☆☆☆leetcode198.打家劫舍题目分析代码☆☆☆☆☆leetcode213.打家劫舍II题目分析代码☆☆☆☆☆leetcode337.打家劫舍III题目分析代码☆☆☆☆☆leetcode198.打家劫舍题目链接:leetcode198.打家劫舍题目分析1.dp数组含义:d......
  • 基于django+vue摄影网站的设计与实现【开题报告+程序+论文】计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展和普及,数字化摄影已成为大众生活的一部分,摄影作品的传播与分享方式也发生了深刻变革。传统的摄影展示与交易方式......
  • [C++ Error] f0202.cpp(13): E2268 Call to undefined function 'system'
    system('pause');解决方法,修改代码:system("pause");[C++Error]f0202.cpp(13):E2268Calltoundefinedfunction'system'错误解释:这个错误表明您在C++代码中尝试调用了一个未定义的函数system。system函数是C标准库中的函数,用于执行一个字符串中给出的命令。在C++中,......