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

19 篇文章 0 订阅
11 篇文章 0 订阅

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

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

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

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

  • 19
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
寻找迷宫最短路径可以用广度优先搜索(BFS)来实现。BFS 从起点开始,逐层向外扩展搜索,直到找到终点或者搜索完所有可达点。在搜索过程中,需要记录每个点的距离和前驱节点,以便找到最短路径。 下面是用 BFS 实现寻找迷宫最短路径的大致步骤: 1. 定义一个队列,将起点入队。 2. 定义一个数组,记录每个点是否被访问过,并初始化为 false。 3. 定义一个数组,记录每个点的距离和前驱节点,并初始化为 -1 和 null。 4. 从队列中取出一个点,将其标记为已访问。 5. 遍历该点的所有邻居,如果邻居没有被访问过,则将其入队,并更新距离和前驱节点。 6. 如果终点被标记为已访问,则找到了最短路径,可以根据前驱节点数组回溯路径。 下面是一个简单的 Python 代码实现: ```python from collections import deque def bfs(maze, start, end): m, n = len(maze), len(maze[0]) visited = [[False] * n for _ in range(m)] distance = [[-1] * n for _ in range(m)] prev = [[None] * n for _ in range(m)] queue = deque([start]) visited[start[0]][start[1]] = True distance[start[0]][start[1]] = 0 while queue: x, y = queue.popleft() for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: nx, ny = x + dx, y + dy if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny] and maze[nx][ny] != '#': visited[nx][ny] = True distance[nx][ny] = distance[x][y] + 1 prev[nx][ny] = (x, y) queue.append((nx, ny)) if (nx, ny) == end: return distance[nx][ny], get_path(prev, start, end) return -1, [] def get_path(prev, start, end): path = [] x, y = end while (x, y) != start: path.append((x, y)) x, y = prev[x][y] path.append(start) return list(reversed(path)) # 示例用法 maze = [ ['#', '#', '#', '#', '#', '#', '#', '#', '#', '#'], ['#', ' ', ' ', ' ', '#', ' ', ' ', ' ', ' ', '#'], ['#', ' ', ' ', ' ', '#', ' ', ' ', ' ', ' ', '#'], ['#', ' ', ' ', ' ', '#', ' ', ' ', ' ', ' ', '#'], ['#', ' ', ' ', ' ', ' ', ' ', '#', '#', ' ', '#'], ['#', ' ', '#', '#', '#', '#', ' ', ' ', ' ', '#'], ['#', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '#'], ['#', '#', '#', '#', '#', '#', '#', '#', '#', '#'], ] start = (1, 1) end = (6, 8) distance, path = bfs(maze, start, end) print('最短距离:', distance) print('最短路径:', path) ``` 注意,以上代码中的 `maze` 是一个二维迷宫数组,'#' 表示墙,' ' 表示空地。`start` 和 `end` 分别为起点和终点的坐标。函数返回最短距离和最短路径

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值