启发式搜索是一种用于解决搜索问题的算法,它通过使用启发式函数来评估哪些路径最有可能导致目标。启发式函数是一种估计,表示从当前节点到目标节点的预期成本。这种方法可以显著地减少搜索空间,提高搜索效率。

# A* 算法

A*(A-Star)算法是启发式搜索中最著名的算法之一。它结合了最佳优先搜索和 Dijkstra 算法的特点:使用启发式信息来指导搜索方向,并确保找到最短路径。

A * 算法的关键在于其评价函数 (f (n) = g (n) + h (n)),其中:

  • (g (n)) 是从起始节点到当前节点 (n) 的实际成本。
  • (h (n)) 是从节点 (n) 到目标节点的预估成本,由启发式函数给出。
  • (f (n)) 是节点 (n) 的总预估成本。

# 示例

假设我们要在一个网格上找到从点 S(起点)到点 T(目标点)的最短路径。障碍物将阻挡路径。我们的目标是找到一条避开障碍物的最短路径。

# 代码

以下是 A * 搜索算法在简化网格中寻找最短路径的 C++ 实现。为了简化,我们假设每个移动的成本相同,启发式函数 (h (n)) 使用曼哈顿距离作为节点 (n) 到目标的预估成本。

#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <cmath>
#include <set>
using namespace std;
struct Node {
    int x, y;
    int g, h;
    Node *parent;
    Node(int x, int y, Node *p = nullptr) : x(x), y(y), g(0), h(0), parent(p) {}
    int f() const { return g + h; }
    bool operator<(const Node& o) const { return f() > o.f(); }
};
int heuristic(int x, int y, int goalX, int goalY) {
    // 使用曼哈顿距离作为启发式函数
    return abs(x - goalX) + abs(y - goalY);
}
bool isValid(int x, int y, int N, int M, const vector<vector<bool>>& obstacles) {
    return x >= 0 && y >= 0 && x < N && y < M && !obstacles[x][y];
}
vector<Node*> aStarSearch(int startX, int startY, int goalX, int goalY, const vector<vector<bool>>& obstacles) {
    int N = obstacles.size(), M = obstacles[0].size();
    priority_queue<Node> openList;
    set<pair<int, int>> closedList;
    openList.emplace(startX, startY);
    while (!openList.empty()) {
        Node current = openList.top();
        openList.pop();
        if (current.x == goalX && current.y == goalY) {
            vector<Node*> path;
            Node *node = new Node(current.x, current.y, current.parent);
            while (node != nullptr) {
                path.push_back(node);
                node = node->parent;
            }
            return path;
        }
        closedList.insert({current.x, current.y});
        vector<pair<int, int>> directions<!--swig0-->;
        for (const auto& dir : directions) {
            int newX = current.x + dir.first;
            int newY = current.y + dir.second;
            if (!isValid(newX, newY, N, M, obstacles) || closedList.find({newX, newY}) != closedList.end())
                continue;
            Node *successor = new Node(newX, newY, new Node(current.x, current.y, current.parent));
            successor->g = current.g + 1;
            successor->h = heuristic(newX, newY, goalX, goalY);
            openList.push(*successor);
        }
    }
    return {};
}
int main() {
    vector<vector<bool>> obstacles = {
        {false, false, false, false},
        {false, true, true, false},
        {false, false, false, false},
        {false, false, true, false}
    };
    auto path = aStarSearch(0, 0, 3, 3, obstacles);
    for (auto it = path.rbegin(); it != path.rend(); ++it) {
        cout << "(" << (*it)->x << ", " << (*it)->y << ") ";
    }
    return 0;
}

在这个例子中, Node 结构体代表网格中的一个节点,包含其位置、从起点到该节点的成本 (g)、从该节点到终点的启发式估计成本 (h) 和父节点指针。 aStarSearch 函数实现了 A * 搜索算法,搜索网格上从起点到终点的最短路径。 heuristic 函数计算启发式函数值,这里使用曼哈顿距离作为估计。

请注意,这个实现主要用于说明 A * 算法的基本思想,并未处理所有边界情况或优化性能。在实际应用中,可能需要更多的考虑,例如更有效的内存管理和复杂场景下的启发式函数选择。