迷宫问题————bfs解决

本文介绍了一种使用广度优先搜索(BFS)算法解决迷宫问题的方法,包括C++和Python两种语言的非递归实现。通过维护节点数组,记录每个节点的坐标、步数和父节点位置,实现了从迷宫入口到出口的最短路径查找。

迷宫问题————bfs解决

输入一个nn的矩阵,以0代表道路,以1代表障碍物,实现一个算法,要求能够给出从入口(默认为左上角)到出口(默认为右下角)的路线。
输入
第一行一个n。
第二行开始是一个(n+2)
(n+2)的矩阵(四周边框为1)
输出
从左上角(1,1)到右下角(n,n)的序列。
测试用例确保具有通路

迷宫问题,采用bfs算法非递归实现,不仅可以求出通路而且可以求出所有通路中最短通途。
C++非递归实现

/* 测试数据 
6
0 1 0 1 0 1
0 1 0 0 0 1
0 1 0 1 0 1
0 1 0 1 0 1
0 1 0 1 0 1
0 0 0 1 0 0
输出
(1,1)
(2,1)
(3,1)
(4,1)
(5,1)
(6,1)
(6,2)
(6,3)
(5,3)
(4,3)
(3,3)
(2,3)
(2,4)
(2,5)
(3,5)
(4,5)
(5,5)
(6,5)
(6,6)
*/ 
#include "iostream"
using namespace std;
class stay		//stay类 记录每一步 
{
	public:
		int x,y,s;		// xy为地图中坐标,s为从原点到当前位置的步数  ox oy为上一步的位置 
		int ox,oy;	
};
int dx[4]={0,1,-1,0};		//地图内四个方向 
int dy[4]={1,0,0,-1}; 
int main()
{
	stay stay[2500];
	int n,nowstay=1,nowtier=1;
	int a[50][50]={0},b[50][50]={0};		//地图 
	int c[1000],m=0;		//存储可行路径 
	int k=0,tier=0;
	int tx=0,ty=0;
	int end=0,zj=0;

	cin>>n;
	for(int i=0;i<n;i++)				//输入地图 
	{
		for(int j=0;j<n;j++)
		{
			cin>>a[i][j];
		}
	}
	
	stay[k].x=0;						//初始化 
	stay[k].y=0;
	stay[k].s=0;
	b[0][0]=1;
	k++;
	
	while(tier<k)						//bfs 每次循环为下一步的四种走法 
	{
		for(int i=0;i<4;i++)			
		{
			tx=stay[tier].x+dx[i];
			ty=stay[tier].y+dy[i];
			if(tx<0||tx>=n||ty<0||ty>=n)			//边界 
			{
				continue;
			}
			if(a[tx][ty]!=1&&b[tx][ty]!=1)			//可行路 
			{
				b[tx][ty]=1;
				stay[k].x=tx;
				stay[k].y=ty;
				stay[k].s=stay[tier].s+1;
				stay[k].ox=stay[tier].x;
				stay[k].oy=stay[tier].y;
				k++;
			}
			if(tx==n-1&&ty==n-1)
			{
				zj=k-1;
				end=1;
				break;
			}
		}	
		if(end==1)
		{
			tier++;
			break;
		}
		tier++;
	}
	c[m]=stay[zj].x ;
	m++;
	c[m]=stay[zj].y;
	m++;
	for(int i=stay[tier].s;i>=0;i--)				// 通过最后走到终点的这一步去寻找上一步并存放在数组c中,一直找到原点 
	{
		for(int j=0;j<zj;j++)
		{
			if(stay[j].s==i&&stay[j].x==stay[zj].ox&&stay[j].y==stay[zj].oy)
			{
				c[m]=stay[j].x ;
				m++;
				c[m]=stay[j].y;
				m++;
				zj=j;
			}
		}
	}
	for(int i=m-1;i>=0;i=i-2)
	{
		cout<<"("<<c[i-1]+1<<","<<c[i]+1<<")"<<endl;
	}
	return 0;
 } 

Python 非递归实现:
实现注意:
主要维护一个节点数组,节点数组中父节点位置变量和子节点位置变量。
为了返回获取路径,每个节点保存当前节点坐标,到该节点步数,该节点父节点在节点数组中的位置。

map=[[0 ,1 ,0 ,1 ,0, 1],
[0, 1 ,0 ,0 ,0, 1],
[0 ,1 ,0 ,1 ,0 ,1],
[0 ,1, 0 ,1, 0 ,1],
[0 ,1 ,0 ,1 ,0, 1],
[0 ,0 ,0 ,1 ,0 ,0]]

dx,dy=[1,0,-1,0],[0,1,0,-1]
log_map=[]
def norecursion(map):
    #初始化
    parent=0
    child_num=0
    s,x,y=0,0,0
    map[x][y]=1
    log_map.append((x,y,s,parent))
    child_num+=1
    while parent<child_num: #终止条件 父节点与子节点重合
        #大循环读取父节点
        x, y,s = log_map[parent][0],log_map[parent][1],log_map[parent][2]
        parent+=1
        for i in range(4):
            #小循环加入子节点
            tx,ty=x+dx[i],y+dy[i]
            #边界条件
            if tx<0 or tx>=len(map) or ty<0 or ty>=len(map[0]) :
                continue
            if map[tx][ty]!=1:
                map[tx][ty]=1
                #加入子节点以及步长和父节点
                child=(tx,ty,s+1,parent-1)
                log_map.append(child)
                child_num += 1
            #终止条件 到达目的地
            if tx==len(map)-1 and ty==len(map[0])-1:
                break
    #通过保存的父节点位置来读取最短路径
    i=len(log_map)-1
    way=[]
    min_s=log_map[i][2]
    while i>0:
        way.append((log_map[i][0],log_map[i][1]))
        i=log_map[i][3]
    way.reverse()
    return  min_s,way
解决迷宫问题中求从入口到出口路径个数的方法有多种,下面介绍两种常见的方法:深度优先搜索(DFS)和广度优先搜索(BFS)。 ### 深度优先搜索(DFS) 深度优先搜索是一种递归的搜索方法,它沿着一条路径尽可能深地探索,直到无法继续,然后回溯到上一个节点,继续探索其他路径。 ```python def dfs(maze, x, y, visited, n): # 判断是否越界、是否为障碍物或是否已经访问过 if x < 0 or x >= n or y < 0 or y >= n or maze[x][y] == 1 or visited[x][y]: return 0 # 判断是否到达出口 if x == n - 2 and y == n - 2: return 1 # 标记当前位置为已访问 visited[x][y] = True count = 0 # 按向右、向下、向左、向上的顺序搜索 directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] for dx, dy in directions: new_x, new_y = x + dx, y + dy count += dfs(maze, new_x, new_y, visited, n) # 回溯,将当前位置标记为未访问 visited[x][y] = False return count def count_paths(maze, n): visited = [[False] * n for _ in range(n)] return dfs(maze, 1, 1, visited, n) ``` ### 广度优先搜索(BFS) 广度优先搜索是一种逐层扩展的搜索方法,它从起点开始,逐层扩展到相邻的节点,直到找到目标节点。 ```python from collections import deque def count_paths_bfs(maze, n): start = (1, 1) end = (n - 2, n - 2) queue = deque([start]) visited = [[False] * n for _ in range(n)] visited[1][1] = True paths = 0 directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] while queue: x, y = queue.popleft() if (x, y) == end: paths += 1 for dx, dy in directions: new_x, new_y = x + dx, y + dy if 0 <= new_x < n and 0 <= new_y < n and maze[new_x][new_y] == 0 and not visited[new_x][new_y]: queue.append((new_x, new_y)) visited[new_x][new_y] = True return paths ``` ### 复杂度分析 - **时间复杂度**:DFS 和 BFS 的时间复杂度均为 $O(m * n)$,其中 $m$ 和 $n$ 分别是迷宫的行数和列数。 - **空间复杂度**:DFS 的空间复杂度为 $O(m * n)$,主要用于递归调用栈和访问标记数组;BFS 的空间复杂度也为 $O(m * n)$,主要用于队列和访问标记数组。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值