【C++ 启发式搜索算法】
文章目录
- 前言
- 一、什么是启发式搜索?
- 1.1 启发式函数
- 1.2 常用算法:A\*
- 二、使用步骤
- 2.1 定义网格地图
- 2.2 定义节点结构
- 2.3 启发函数实现(曼哈顿距离)
- 2.4 A\* 主逻辑
- 2.5 测试
- 三、运行结果示例
- 总结
前言
启发式搜索是人工智能和路径规划中非常重要的一类搜索算法。与传统的暴力搜索不同,它通过一个 启发函数(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* 算法都是非常常用的基础模块。