文章目录
前言
启发式搜索是人工智能和路径规划中非常重要的一类搜索算法。与传统的暴力搜索不同,它通过一个 启发函数(Heuristic Function) 来引导搜索过程,更加智能和高效。最经典的启发式搜索算法是 A* 算法,广泛用于游戏寻路、路径规划、机器人导航等领域。
一、什么是启发式搜索?
启发式搜索是一种在搜索过程中结合了“经验”的算法,它利用一个启发函数 h ( n ) h(n) h(n) 来估算从当前节点到目标节点的代价,从而决定搜索的方向。
1.1 启发式函数
启发函数通常记作:
f ( n ) = g ( n ) + h ( n ) f(n) = g(n) + h(n) f(n)=g(n)+h(n)
- g ( n ) g(n) g(n):从起点到当前节点的实际代价
- h ( n ) h(n) h(n):从当前节点到终点的估计代价(启发函数)
- f ( n ) f(n) f(n):综合代价(用于优先队列排序)
1.2 常用算法:A*
A* 算法是启发式搜索的经典实现,它通过不断扩展估计代价最小的节点,最终找到最优路径。
二、使用步骤
2.1 定义网格地图
我们使用一个二维网格来表示地图,0 表示可通行,1 表示障碍物。
const int ROW = 5;
const int COL = 5;
int grid[ROW][COL] = {
{0, 1, 0, 0, 0},
{0, 1, 0, 1, 0},
{0, 0, 0, 1, 0},
{1, 1, 0, 0, 0},
{0, 0, 0, 1, 0}
};
2.2 定义节点结构
struct Node {
int x, y;
int g, h;
Node* parent;
Node(int x, int y, int g, int h, Node* parent = nullptr)
: x(x), y(y), g(g), h(h), parent(parent) {}
int f() const { return g + h; }
// 用于优先队列中排序(小顶堆)
bool operator>(const Node& other) const {
return this->f() > other.f();
}
};
2.3 启发函数实现(曼哈顿距离)
int heuristic(int x1, int y1, int x2, int y2) {
return abs(x1 - x2) + abs(y1 - y2);
}
2.4 A* 主逻辑
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
using namespace std;
bool isValid(int x, int y) {
return x >= 0 && x < ROW && y >= 0 && y < COL && grid[x][y] == 0;
}
void reconstructPath(Node* end) {
vector<pair<int, int>> path;
while (end) {
path.push_back({end->x, end->y});
end = end->parent;
}
reverse(path.begin(), path.end());
cout << "路径为: ";
for (auto [x, y] : path)
cout << "(" << x << "," << y << ") ";
cout << endl;
}
void aStar(int sx, int sy, int ex, int ey) {
priority_queue<Node*, vector<Node*>, function<bool(Node*, Node*)>> openSet(
[](Node* a, Node* b) { return a->f() > b->f(); });
vector<vector<bool>> visited(ROW, vector<bool>(COL, false));
openSet.push(new Node(sx, sy, 0, heuristic(sx, sy, ex, ey)));
int dirs[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}};
while (!openSet.empty()) {
Node* current = openSet.top();
openSet.pop();
if (current->x == ex && current->y == ey) {
reconstructPath(current);
return;
}
visited[current->x][current->y] = true;
for (auto [dx, dy] : dirs) {
int nx = current->x + dx;
int ny = current->y + dy;
if (isValid(nx, ny) && !visited[nx][ny]) {
int g = current->g + 1;
int h = heuristic(nx, ny, ex, ey);
openSet.push(new Node(nx, ny, g, h, current));
}
}
}
cout << "没有找到路径!" << endl;
}
2.5 测试
int main() {
int startX = 0, startY = 0;
int endX = 4, endY = 4;
aStar(startX, startY, endX, endY);
return 0;
}
三、运行结果示例
假设起点在 (0, 0),终点在 (4, 4),控制台输出类似如下:
路径为: (0,0) (1,0) (2,0) (2,1) (2,2) (3,2) (3,3) (3,4) (4,4)
总结
本文介绍了启发式搜索的基本概念和 A* 算法的 C++ 实现。通过启发函数引导搜索方向,可以显著提升路径搜索的效率。启发式搜索的核心在于设计一个合理的启发函数,不同的启发函数会影响搜索速度和结果是否最优。在实际项目中,比如自动驾驶、机器人路径规划或地图导航中,A* 算法都是非常常用的基础模块。
8026

被折叠的 条评论
为什么被折叠?



