【蓝桥OJ:BFS】2019省赛:迷宫 python实现

题目链接:https://www.lanqiao.cn/problems/602/learning/
思路:
1.基本算法:最短路径迷宫题采用BFS(广搜)算法
2.迷宫图的储存方法:使用二维列表逐行逐列储存地图mp
3.走迷宫应注意:
1)设置标记已走过的平行地图vis,设置走迷宫jued()函数,边界判断,用if来走迷宫;
2)储存路径的数据结构是重点,此处采用队列deque。为实现BFS需要一个空队列deque(run)来储存BFS过程:探索结点A时,判断一遍结点A的四个neighbor(相邻四点),储存能走的下一个结点入队run,随后pop将结点A弹出队列,如此往复就是BFS的过程;
4.字典序小技巧:每个结点的探图方向用‘D,L,R,U’的字典序顺序,这样BFS搜出来的第一条路径就是字典序最小的最短路径了
5.最短路径储存方法:前驱结点记录法:探图时用字典同时记录每个点的前驱结点
6.通过路径遍历四个方向来生成脚印

代码:

import  collections
s='''01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000'''

mp=[[int(i) for i in j ]for j in s.split('\n')]
vis=[[False for i in j ]for j in s.split('\n')]#标记访问
run=collections.deque()  #BFS用队列
path=[]  #路径
dire=[(0,1),(-1,0),(1,0),(0,-1)]  #字典序D,L,R,U


def jued(x,y):  #走迷宫函数
	if mp[y][x]==0 and vis[y][x]==False:
		return True
dic={}  #用字典记录前驱结点
def bfs():  #广搜
    run.append((0,0))
    while len(run)!=0:
        temp=0
        x=run[0][0]
        y=run[0][1]
        vis[0][0]=True
        for i in range(4):
                newx = x+dire[i][0]
                newy = y+dire[i][1]
                if 0<=newx<=49 and 0<=newy<=29:
                        if jued(newx,newy)==True:
                                vis[newy][newx]=True
                                run.append((newx,newy))
                                dic[(newx,newy)]=(x,y)
                                if newx==49 and newy==29 :return 0
        run.popleft()		
bfs()

def find_path(x,y):#递归串联出最短路径
        path.append((x,y))
        if x==y==0:
                return path
        else:
                return find_path(dic[(x,y)][0],dic[(x,y)][1])

find_path(49,29)
path=path[::-1]  #倒叙路径
step=collections.deque()  #脚印


for i in range(1,len(path)):#生成脚印
        for j in range(4):
                if path[i][0]==path[i-1][0]+dire[j][0] and path[i][1]==path[i-1][1]+dire[j][1]:
                      
                      if j==0:step.append('D')
                      elif j==1:step.append('L')
                      elif j==2:step.append('R')
                      elif j==3:step.append('U')
                      break


print(''.join(step))#输出格式



#DFS输出一条路径(并非最短)方法:
'''import sys
sys.setrecursionlimit(2000)
s='......'

mp=[[int(i) for i in j] for j in s.split('\n')]
vis=[[False for i in j]for j in s.split('\n')]
di=[[-1,0],[0,-1],[1,0],[0,1]]  #向左、上、右、下
path=[]
print(mp[29][49])
def dest(x,y):
    if x==49 and y==29:
        #True已到终点
        return True                
    else:return False
def check(x,y):
    if x in range(0,50) and y in range(0,30) and vis[y][x]==False and mp[y][x]==0 :#条件检查
        return True
    else : return False

def dfs(x,y):
    if dest(x,y):
        return True  #走到终点
    vis[y][x]=True
    for i in range(4):
        newx=x+di[i][0]
        newy=y+di[i][1]
        if check(newx, newy):
            if i==0 :
                path.append(('L',newx,newy))
                return dfs(newx,newy)
            if i==1 :
                path.append(('U',newx,newy))
                return dfs(newx,newy)
            if i==2 :
                path.append(('R',newx,newy))
                return dfs(newx,newy)
            if i==3 :
                path.append(('D',newx,newy))
                return dfs(newx,newy)
        else:continue
    path.pop() #回溯
    vis[path[-1][2]][path[-1][1]]=False
    return dfs(path[-1][1],path[-1][2])
dfs(0,0)
result=[]
for i in range(len(path)):
    result.append(path[i][0])
print(''.join(result))    '''

总结:
BFS算法是最短路径问题最基础的方法。此类搜索题书写的代码量较多,采用的数据结构较多,如这题列表、元组、字典都灵活运用到了,但思路明确,算法不算复杂。

你可能感兴趣的:(蓝桥,宽度优先,python,蓝桥杯,bfs,dfs)