前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >寻路(待完成)

寻路(待完成)

作者头像
gojam
发布2019-10-14 15:24:23
4680
发布2019-10-14 15:24:23
举报
文章被收录于专栏:gojam技术备忘录gojam技术备忘录

用C++实现寻路的几种方法。

地图

思前想后我决定用链表来存储地图,也就是用vector<int>按顺序存储地图的节点,由于地图一般是矩形的,知道高度与宽度后我们无需再存储位置信息,每个节点的内容可以是地形高度。用数组也是可以的,但栈中的数组需要确定大小,动态数组很好,但为了方便删除元素还是用效率低的vector容器吧。

points存储每个节点的高度,target存储目标节点的序号,landing存储登陆点的序号,width与length用于根据序号推算节点位置,height是寻路对象能够跨越的最大高度,track记录路径,find标记是否已到达所有终点。除了track与find,其余成员变量都要初始化。

代码语言:javascript
复制
class Graph{
 private:
  vector<int> points;
  vector<int> target;
  int landing;
  int width,length;
  int height;
  vector<int> track;
  bool find=false;
}

DFS

先写一个启动DFS的函数,用于未找到路径时输出结果。

代码语言:javascript
复制
    void startDFS()
    {
        DFS(this->landing);
        if (this->find == false)
        {
            cout << "未找到路径!" << endl;
        }

    }

DFS主函数检查周围的点是否已访问或符合规则,然后访问。访问后节点height被标记为-1,checkEnd用于判断是否已到达全部终点并修改find的值,checkNeighbor用于把将要访问的点放入neighbor。

代码语言:javascript
复制
    bool DFS(int start)
    {
        vector<int> neighbor;
        //如果已经找到那么结束
        if (this->find == true)
        {
            return false;
        }

        //如果已经访问过那么返回
        if (points[start]==-1)
        {
            return false;
        }
        else
        {
            points[start]=-1;
            track.push_back(start);
        }

        checkEnd(start);

        checkNeighbor(start, &neighbor);

        for (int i = 0; i < neighbor.size(); i++)
        {
            DFS(neighbor[i]);
        }
        track.pop_back(); //返回上级时弹出
    }

checkEnd函数:

代码语言:javascript
复制
    void checkEnd(int start)
    {
        for (int k = 0; k < target.size(); k++)
        {
            if (start == target[k])
            {
                cout << "经过了" << start << endl;
                target[k] = -1; //标记已到达
                bool visitedAll = true;
                for (int i = 0; i < target.size(); i++)
                {
                    if (target[i] != -1)
                    {
                        visitedAll = false;
                    }
                }
                if (visitedAll == true)
                {
                    cout << "已全部到达!" << endl;
                    this->find = true;
                    for (int i = 0; i < track.size(); i++)
                    {
                        cout <<"("<< track[i]/width <<","<<track[i]%width<<")"<< endl;
                    }
                }
            }
        }
    }

checkNeighbor函数,通过有关计算确定一个位置的上/下/左/右等位置是否存在节点。

代码语言:javascript
复制
    void checkNeighbor(int start, vector<int> *neighbor)
    {
        int leftTop = -1, top = -1, rightTop = -1, left = -1, right = -1, bottom = -1, leftBottom = -1, rightBottom = -1;
        bool hasLeft = false, hasRight = false, hasTop = false, hasBottom = false;

        if (start % width != 0)
        {
            hasLeft = true;
        }
        if ((start + 1) % width != 0)
        {
            hasRight = true;
        }
        if (start - width >= 0)
        {
            hasTop = true;
        }
        if (start + width < width * height)
        {
            hasBottom = true;
        }
        //8个方向的数组序号
        if (hasTop && hasLeft)
        {
            leftTop = start - width - 1;

            if (abs(points[start] - points[leftTop]) >= maxZ)
            {
                leftTop = -1;
            }
        }
        if (hasTop)
        {
            top = start - width;
            if (abs(points[start] - points[top]) >= maxZ)
            {
                top = -1;
            }
        }
        if (hasRight && hasTop)
        {
            rightTop = start - width + 1;
            if (abs(points[start] - points[rightTop]) >= maxZ)
            {
                rightTop = -1;
            }
        }
        if (hasLeft)
        {
            left = start - 1;
            if (abs(points[start] - points[left]) >= maxZ)
            {
                left = -1;
            }
        }
        if (hasRight)
        {
            right = start + 1;
            if (abs(points[start] - points[right]) >= maxZ)
            {
                right = -1;
            }
        }
        if (hasLeft && hasBottom)
        {
            leftBottom = start + width - 1;
            if (abs(points[start] - points[leftBottom]) >= maxZ)
            {
                leftBottom = -1;
            }
        }
        if (hasRight && hasBottom)
        {
            rightBottom = start + width + 1;
            if (abs(points[start] - points[rightBottom]) >= maxZ)
            {
                rightBottom = -1;
            }
        }
        if (hasBottom)
        {
            bottom = start + width;

            if (abs(points[start] - points[bottom]) >= maxZ)
            {
                
                bottom = -1;
            }
        }
        //添加到neighbor
        if (leftTop != -1)
        {
            //neighbor.push_back(&points[leftTop]);
            neighbor->push_back(leftTop);
        }
        if (top != -1)
        {
            //neighbor.push_back(&points[top]);
            neighbor->push_back(top);
        }
        if (rightTop != -1)
        {
           
            neighbor->push_back(rightTop);
        }
        if (left != -1)
        {
            
            neighbor->push_back(left);
        }
        if (right != -1)
        {
           
            neighbor->push_back(right);
        }
        if (leftBottom != -1)
        {
           
            neighbor->push_back(leftBottom);
        }
        if (bottom != -1)
        {
   
            neighbor->push_back(bottom);
        }
        if (rightBottom != -1)
        {
      
            neighbor->push_back(rightBottom);
        }
    }

BFS

虽然我把BFS遍历写出来了,但BFS不方便记录轨迹,因为访问元素是依次加入队列的,之间没有父子关系。如果要记录路径的话,需要知道路径上每个节点的父节点,也就是要形成一颗BFS树:每个节点都记录自己的父节点。

那么BFS记录轨迹的方法就是,将邻居节点加入队列时,节点信息要包括本节点,收集从队列中弹出的节点(收集访问过的节点,可以组织成一棵树),当找到终点时,反向寻找出发点。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年10月12日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 地图
  • DFS
  • BFS
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档