回溯法之迷宫最短路径,c++实现

龚景
• 阅读 2482

回溯法之迷宫最短路径,c++实现

迷宫的算法很多,但是解释原理的却很少,在这里我利用自己的亲身经历来讲解一下求解迷宫的原理

  1. 迷宫求解可以利用栈结构,即深度优先,探索一个位置就标记,通则走
  2. 不通则后退寻找下一个位置,可以求出通路,简单但是不一定是最短路径
  3. 这里求最短路径利用的是广度优先的思想,什么是广度优先,利用队列实现,一个元素出队
  4. 然后访问这个元素相邻的所有元素,原理是,一个二维数组,0表示墙,1表示路,这里我利用随机数生成0和1,4个方向
  5. 在广度优先算法的思想下,队头元素出队,然后广度依次访问他的4个方向,依次入队,并记下他们的前一个坐标在队列中的位置
  6. 重复直到出对的是终点,在找到终点后,利用每一个位置都有前一个坐标在队列中的下标进行回访,访问到起点即走了一遍找到的路径,此时便可正向输出路径即可。

回溯法之迷宫最短路径,c++实现
广度优先访问的过程就是,假设现在队头是5,5出队后,访问5的相邻元素,即将6,8,4,2入队,这里是顺时针方向,一次类推。
假设这里9个元素全部是路,一开始1入队,然后1出队,访问四周,2,4依次入队,前一个坐标是1,2出队,3,5入队,前一个坐标是2,4出队,7入队,前一个坐标是4,3出队,6入队,前一坐标是3,5出队,8入队,前一坐标是8,6出队,9入队,前一坐标是6,访问了终点9,结束入队,从9开始回访,9->6->3->2->1 即找到最短路径。

#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
struct Node
{
    int data;
    int flag;
};
struct Path
  {
  int xpath;
  int ypath;
  int pox;    //在队列中的下标 
  };

  class Maze
  {
  private:
      int n, m;     //迷宫的行和列 
      Node *maze;   //迷宫存放 
      Path *que;
      int top = -1;
      int front = -1;
      int rear = -1;
  public:
    
    void create()
    {
        int i, j;
        cout<<"输入迷宫的行和列:";
        cin>>n>>m;
        maze = new Node[n*m];
        srand(time(NULL));
        for(i = 0; i<n; i++)
        {
            for(j = 0; j<m; j++)
            {
                int temp = rand()%4;
                if(temp != 1) maze[i*m+j].data = 1;
                else maze[i*m+j].data = 0;
                maze[i*m+j].flag = 0;
            }
        }
        maze[0].data = 8;  //设置起点 
        maze[n*m-1].data = 1;
        show();
    } 
    
    /*搜索路径*/ 
    void seek_road()   /*先实现一个路径先*/ 
    {
        //path = new Path[n*m];
        int x1, y1;
        que = new Path[n*m];                  //利用广度优先实现最短路径
        que[0].xpath = 0;
        que[0].ypath = 0;
        que[0].pox = 0;
        maze[0].flag = 1;
        rear++;
        while(front != rear)
        {
            int x = que[(++front)%(n*m)].xpath;  //获取队头的坐标,然后将其四周的通路进队,知道操作完队尾元素 
            int y = que[front%(n*m)].ypath;
        //    path[++top] = que[front];
            if(judge_head()) return;
            if(y+1<m)
                push_road(x,y+1);
            if(x+1<n)
                push_road(x+1,y);
            if(y-1>=0)
                push_road(x,y-1);
            if(x-1>=0)
                push_road(x-1,y);
        }    
        cout<<"没有通路!!"<<endl;
    }
             
            
    void show()
    {
        for(int i = 0; i<n; i++)
        {
            for(int j = 0; j<m; j++)
            {
                if(maze[i*m+j].data == 8) cout<<"■ "; 
                else cout<<maze[i*m+j].data<<"  ";
            }
            cout<<endl;
        }
    }
    
    int judge_head()
    {
        int k=1;
        if(que[front].xpath == n-1 && que[front].ypath == m-1) 
        {
            
            cout<<"找到迷宫的通路!"<<endl;
            int x = que[front].xpath;
            int y = que[front].ypath;
            int t = que[front].pox;    //前一个坐标在队列的下标 
            while(x != 0 || y != 0)
            {
                maze[x*m+y].data = 8;
                x = que[t].xpath;
                y = que[t].ypath;
                t = que[t].pox;
                k++;
            }
            show();
            cout<<"路径长度为:"<<k<<endl; 
            return 1;
        }
        return 0;
    }
    
    void push_road(int x, int y)
    {
        if(maze[x*m+y].data == 1 && maze[x*m+y].flag == 0)
        {
            que[(++rear)%(n*m)].xpath = x;
            que[rear%(n*m)].ypath = y;
            que[rear%(n*m)].pox = front;   //设置上一个坐标在队列中的位置 
            maze[x*m+y].flag = 1;
        }
    }
};

int main()
{ 
  Maze *ma = new Maze();         /*待解决-迷宫最短路径问题*/ 
  ma->create();
  ma->seek_road();
  return 0;
} 

ps:这是个人学习过程中得体会,如果有错误得地方,欢迎留言提醒,定会及时修改,如果觉得有帮助,可以加个关注,后面还会有其他算法得原理分析和代码,也可私聊我哦

点赞
收藏
评论区
推荐文章
徐小夕 徐小夕
5年前
《前端实战总结》之使用解释器模式实现获取元素Xpath路径的算法
前端领域里基于javascript的设计模式和算法有很多,在很多复杂应用中也扮演着很重要的角色,接下来就介绍一下javascript设计模式中的解释器模式,并用它来实现一个获取元素Xpath路径的算法。上期回顾《前端实战总结》之迭代器模式的N1种应用场景(https://juejin.im/post/6844904008616771591)
Wesley13 Wesley13
4年前
Java8与迷宫回溯问题
文章目录引入(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fweixin_44575152%2Farticle%2Fdetails%2F109641186%23_2)代码(https://www.oschina.net/
Stella981 Stella981
4年前
Bellman
一、BellmanFordBellmanFord算法是一种用于计算带权有向图中单源最短路径(当然也可以是无向图)。与Dijkstra相比的优点是,也适合存在负权的图。若存在最短路(不含负环时),可用BellmanFord求出,若最短路不存在时,BellmanFord只能用来判断是否存在负环。松弛:    每次松弛操作
Wesley13 Wesley13
4年前
unity 使用深度优先搜索生成迷宫之二
unity使用深度优先搜索生成迷宫之二之前写过一篇使用深度优先搜索生成随机迷宫的文章https://www.cnblogs.com/JinTHwang/p/9599913.html(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.cnblogs.com%2FJinT
Stella981 Stella981
4年前
HDU 3416 Marriage Match IV (Dijkstra+最大流)
题意:N个点M条边的有向图,给定起点S和终点T,求每条边都不重复的ST的最短路有多少条。分析:首先第一步需要找出所有可能最短路上的边。怎么高效地求出呢?可以这样:先对起点S,跑出最短路;对于每条边e(u,v,w),若d\u\wd\v\。那么e就是最短路上的一条边。在前向星存储的图中遍历即可。网上还有题解用的方法是分别从S和T跑两
Wesley13 Wesley13
4年前
UVA11624 Fire!
题目:乔在迷宫中工作。不幸的是,迷宫的一部分着火了,迷宫的主人没有制定火灾的逃跑计划。请帮助乔逃离迷宫。根据乔在迷宫中的位置以及迷宫的哪个方块着火,你必须确定火焰烧到他之前,乔是否可以离开迷宫,如果能离开他能跑多快。乔和火每分钟移动一个方格,上、下、左、右,四个方向中的一个。火势向四个方向同时蔓延。乔可以从迷宫的任何一个边界逃离
Stella981 Stella981
4年前
Bailian4129 变换的迷宫【BFS】
4129:变换的迷宫(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fbailian.openjudge.cn%2Fpractice%2F4129%3Flang%3Den_US)总时间限制:1000ms内存限制:65536kB描述你现在身处一个R\C的迷
Stella981 Stella981
4年前
Dijkstra算法
引言Dijkstra算法主要应用在寻找带正边权的图中顶点之间的最短路径。这种例子在生活中非常多,比如导航软件自动规划路径,路径最短或用时最少的路径总是作为最优路径返回给你;又比如我大天朝最常见的找人办事,有的时候我们没法直接找到可以帮忙的人,就需要再找别人帮忙,又或者关系不够铁,找人花的代价很大,我们总是潜意识里找关系最铁并中转最少的人去帮忙。
贾蔷 贾蔷
9个月前
NOIP 2000 提高组 洛谷1004题(方格取数)解题思路与C++代码解析
一、题目描述简要描述题目:例如,在一个n×n的方格图中,每个格子包含一个正整数。需要选择两条从左上角到右下角的路径,路径可重复经过格子,但两条路径除起点和终点外不能相交。求两条路径数字和的最大值。二、解题思路与算法分析1.问题分析1.问题核心是求解两条不交
贾蔷 贾蔷
9个月前
洛谷P11228地图探险题解(CSP-J 2024真题)
一、题目重述给定n×m的二维矩阵表示探险地图,每个格子可能是:平地('.')障碍物('')起点('S')终点('E')求从起点到终点的最短路径步数,无法到达则输出1。二、核心算法:BFS广度优先搜索选择原因:BFS是解决无权图最短路径问题的最优方案,时间复
深度学习 深度学习
7个月前
洛谷P1443题:用BFS算法解决马走日问题
一、问题理解题目要求计算马从初始位置出发,到达棋盘上每个位置的最少步数。马在国际象棋中走"日"字,有8种可能的移动方向。二、选择()是解决这类问题的理想选择,因为:1.BFS按,第一次访问到某个位置时就是最短路径2.天然适合处理网格类问题3.实现简单直观实