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

602 阅读2分钟

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

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

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

广度优先访问的过程就是,假设现在队头是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 #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:这是个人学习过程中得体会,如果有错误得地方,欢迎留言提醒,定会及时修改,如果觉得有帮助,可以加个关注,后面还会有其他算法得原理分析和代码,也可私聊我哦