启发式搜索 -- 优先队列priority_queue

news/2024/6/17 1:50:19 标签: c++, 队列, 算法

C++ 启发式搜索 – 优先队列priority_queue

广搜会四面八方搜索很多无用路径,用启发式搜索解决只向目标方向进行搜索,避免四面八方搜索

  • 实现:1)起点开始搜索。 2)预估到终点的距离
#include <iostream>
#include <queue>
#include <cmath>
using namespace std;

char mmap[105][105]; //地图大小
int cnt, //记录目前为止搜过了多少个点
n, m, //地图大小
sx, sy, //起点坐标
ex, ey, //终点坐标
mark[105][105][2], //去重 记录路径
dir[8][2] = { 0, 1, 1, 0, 0, -1, -1, 0, 1, 1, 1, -1, -1, 1, -1, -1 }; //方向数组

struct node {
    int x, y, step; //step : 到坐标(x,y)需要走几步
    double dis; //预估起点到终点的距离
    bool operator< (const node& b) const { //优先队列默认大顶堆,重载<实现小顶堆
        return this->step + this->dis > b.step + b.dis; //起点距离+预估距离:和越小越出优先队列
    }
};

void func(int x, int y) {
    if (mmap[x][y] == 'S') return; //结束条件:递归到了起点
    mmap[x][y] = 'o';
    func(mark[x][y][0], mark[x][y][1]); //改父节点
}

void print() {
    cout << "############## cnt = " << cnt << "##################" << endl;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            cout << mmap[i][j];
            if (mmap[i][j] == 'x')
                mmap[i][j] = '*'; //* : 表示之前已经搜索过此点
        }
        cout << endl;
    }
    cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << endl;
}

double cal_dis(int x, int y) { //计算到终点的直线距离
    return sqrt((ex - x) * (ex - x) + (ey - y) * (ey - y));
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) {
            cin >> mmap[i][j];
            (mmap[i][j] == 'S') && (sx = i) && (sy = j);
            (mmap[i][j] == 'T') && (ex = i) && (ey = j);
        }
    priority_queue<node> que;
    que.push({sx, sy, 0, cal_dis(sx, sy) }); //压入起点
    while (!que.empty()) {
        node tmp = que.top();
        que.pop();
        for (int i = 0; i < 8; ++i) {
            int x = tmp.x + dir[i][0],
                y = tmp.y + dir[i][1]; //新点坐标
            if (mmap[x][y] == 'T') { //走到了终点
                func(tmp.x, tmp.y); //打印走过的路径
                print();
                cout << ++tmp.step << endl;
                return 0;
            }
            if (mmap[x][y] == '.') { //表示可以走的路径
                que.push({x, y, tmp.step + 1, cal_dis(x, y)});
                mmap[x][y] = 'x'; //去重
                mark[x][y][0] = tmp.x; //横坐标从tmp.x来的
                mark[x][y][1] = tmp.y; //纵坐标从tmp.y来的
                ++cnt;
                if (cnt % 10 == 0) print();
            }
        }
    }
    cout << "cant not via the end " << endl;
    return 0;
}

http://www.niftyadmin.cn/n/1515532.html

相关文章

opencv: C++实现将彩色图转换为灰色图

#include <opencv2/opencv.hpp> using namespace cv;int main() {Mat src, dst;src imread("1.png"); //处理图像的地址dst.create(src.rows, src.cols, CV_8UC1);for (int i 0; i < src.rows; i)for (int j 0; j < src.cols; j)dst.at<uchar>(…

邻接矩阵:Floyd算法 邻接表:Dijkstra算法

邻接表 优点&#xff1a;1&#xff09;省空间&#xff0c;空间复杂度(m) ---------2&#xff09;快速访问以某一点为起点的所有边 缺点&#xff1a;不能快速判断两点间关系 应用&#xff1a;Floyd算法 ​ 求多源最短路径&#xff0c;即任意两点间的最短路径。时间复杂的 O(n^…

【链式向前星】算法 并求最短路径

链式前向星 采取头插法的静态链表&#xff08;数组模拟链表&#xff09;&#xff0c;存放着多个静态链表 有2个数组&#xff1a;head一维数组存放边。 另一个二维数组&#xff0c;第一维edge存放边&#xff1b;第二维存放next。edg[i] 的 next 表示与 i 这条边同起点的上条边的…

基于队列优化的Bellman-Ford算法

Bellman-Ford算法 求单源最短路径 &#xff0c;暴力求解&#xff0c;时间复杂度O(n * m)可以处理带有负数的边&#xff08;负权边&#xff09;n条边最多需要遍历 n-1 次 #include <iostream> #include <cstring> using namespace std;struct edge { //记录每条边…

最小生成树 - Kruskal算法

边进行求解&#xff1a; 1&#xff09;按照n条边的权值从小到大进行排序 2&#xff09;从小到大进行遍历 3&#xff09;依次判断边的一侧与另一侧是否相连。不相连进行选中连接&#xff0c;相连则跳过 4&#xff09;重复步骤3直至有n-1条边&#xff0c;此时为最小生成树 并查集…

最小生成树 - Prim算法

点进行求解 1&#xff09;随意定一个起点 2&#xff09;所有定的点中&#xff0c;向外面寻找所有可以连通的边 3&#xff09;每次选一条权值最小的边&#xff0c;作为最小生成树的新边&#xff0c;并得到定的新点 4&#xff09; 重复步骤23直至有n-1条边&#xff0c;此时为最小…

图:拓扑排序 实现输出全部拓扑排序

拓扑排序 求解过程&#xff1a; 1&#xff09;计算所有点的入度值 2&#xff09;寻找入度为0的点 3&#xff09;寻找这个点影响的其他连通点并把它们的入度值减去1 4&#xff09;循环进行23步&#xff0c;直到所有点都找到 可以判断图是否有环&#xff1a;若寻找不到入度为0的…

拓扑排序实现【635.神经网络】

#include <iostream> #include <vector> //使用邻接表 #include <queue> //拓扑排序使用队列 using namespace std;int n; //点的数量 int m; //边的数量 int inDegree[1001]; //保存入度数量 int outDegree[1001]; //保存出度数量 int c[105]; int u[105];s…