【题目描述】

给一个二维列表,表示迷宫(0表示通道,1表示围墙)。给出算法,求一条走出迷宫的路径。

你也能看得懂的python算法书pdf python算法指南程序员经典_出队

一、栈——深度优先搜索

1.回溯法

2.思路:从一个节点开始,上下左右任意找下一个能走的点,当找不到能走的点时,退回上一个点寻找是否有其他方向的点。

3.使用栈存储当前路径

4.使用匿名函数lambda定义坐标上下左右走,可以看看下面这篇

Python中lambda使用简单小结_alxe_made的博客-CSDN博客_lambda python用法lambda简单介绍1. 什么是lambda 简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。这一用法跟所谓 λ 演算(题目说明里的维基链接)的关系,有点像原子弹和质能方程的关系,差别其实还是挺大的。举例子说明:g = lambda x : x+1g(1)输出:2可以这样...

maze=[
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
]#1代表围墙,0代表可以走的路

#匿名函数
dirs=[
    #x代表行,y代表列
    lambda x,y:(x+1,y),#上
    lambda x,y:(x,y+1),#右
    lambda x,y:(x-1,y),#下
    lambda x,y:(x,y-1)#左
]

def maze_path(x1,y1,x2,y2):#起点坐标(x1,y1),终点坐标(x2,y2)
    stack=[]
    test=1
    stack.append((x1,y1))
    while(len(stack)>0):#如果栈中没有元素,代表起点的上下左右都不通,推出循环
        curNode=stack[-1]#表示当前的坐标以及for循环以后的新坐标,因为栈是先进后出的,所以stack[-1]表示最后一个坐标
        
        if curNode[0]==x2 and curNode[1]==y2:#表示走到终点了
            for i in stack:
                print(i)
            return True
        for dir in dirs:
            nextNode=dir(curNode[0],curNode[1])#下一个坐标,每个curNode都表示一个元组:0表示第x行,1表示第y列
            #判断下一跳是否为0,如果是0则将nextNode保存到栈,标记任意数,然后break,下一跳
            if maze[nextNode[0]][nextNode[1]]== 0:#等于0表示能走
                stack.append(nextNode)#有路则保存到栈中
                maze[nextNode[0]][nextNode[1]]=2#标记已经走过的路
                break #能找到一个就直接下一跳
        else:#回退
            
            maze[nextNode[0]][nextNode[1]]=2#走不通也代表走过,所以也要标记一下
            stack.pop()#回退
    #栈空
    else:
        print("没有路")
        return False

maze_path(1,1,8,8)

【运行代码】

你也能看得懂的python算法书pdf python算法指南程序员经典_算法_02


二、队列——广度优先搜索

1.找终点

【解题思路】

从一个节点开始,寻找所有接下来能继续走的点,继续不断寻找,直到找到出口。

使用队列存储当前正在考虑的节点。

你也能看得懂的python算法书pdf python算法指南程序员经典_匿名函数_03

可以用这张图来解释,扩起来的是用来存储当前的节点,一个节点进站,之前的父节点需要出列

假设x=13是终点,则下面延伸就是:(红色的代表队列里存储的数)

1 2 3 4 5 6 7

1 2 3 4 5 6 7 8 9 #6出队,将8,9元素加入队列中

1 2 3 4 5 6 7 8 9 10 #接着7出队,将10元素加入队列中

1 2 3 4 5 6 7 8 9 10 11#依次出队进队操作,直到终点加入到队中,结束

1 2 3 4 5 6 7 8 9 10 11 12

1 2 3 4 5 6 7 8 9 10 11 12 13

 2.输出路径

【解题思路】

从终点开始倒着找起点,存储到列表中

出队序列: 1  2  3  4  5  6  7

哪点来的:-1  0  1  2  2  3  4 

假设7这个点是要找的终点,则返回原先来的那个点

所以7是由5过来的,所以跳转到下标2,然后5又是由3过来的,所以输出下标2,然后依次类推

输出下标 1,0,-1,得到路径。


【代码运算】

需要注意的是,要创建一个队列来存储移出队列的元素

from collections import deque #导入队列
#首先直接套用栈的迷宫和匿名函数
maze=[
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
]#1代表围墙,0代表可以走的路

#匿名函数
dirs=[
    #x代表行,y代表列
    lambda x,y:(x+1,y),#上
    lambda x,y:(x,y+1),#右
    lambda x,y:(x-1,y),#下
    lambda x,y:(x,y-1)#左
]
#输出路径
def print_r(path):
    #path里最后一个元素是终点
    curNode=path[-1]#终点
    realpath=[]#新列表
    #当第三个元素不是-1一直循环
    while curNode[2]!=-1:
        #如果不是-1,则把curNode放入新的列表里
        realpath.append((curNode[0],curNode[1]))
        #curNode[2]是由上一个点(len(path)-1)得来的
        #所以这样可以得到上一个点
        curNode=path[curNode[2]]
    #当等于-1时候,代表起点,将起点输出
    realpath.append((curNode[0],curNode[1]))
    realpath.reverse()#倒序
    for node in realpath:
        print(node)
def maze_path_queue(x1,y1,x2,y2):
    queue=deque()#创建一个队列
    queue.append((x1,y1,-1))#创建三维列表(起点坐标,下标)
    path=[] #用于存储被队列移除的数的下标
    while len(queue)>0:#队列为空的时候表示上下左右都走不通
        curNode=queue.popleft()#表示移出队列的第一个数
        path.append(curNode)
        if curNode[0]==x2 and curNode[1]==y2:
            #找到终点,输出所有路径
            print_r(path)
        for dir in dirs:
            nextNode = dir(curNode[0],curNode[1])
            if maze[nextNode[0]][nextNode[1]]==0:
                queue.append((nextNode[0],nextNode[1],len(path)-1))
                maze[nextNode[0]][nextNode[1]]=2 #标记为已经走过的路
                #广义搜索不需要break
    #当队列为空时
    else:
        print("队列为空")
        return False
maze_path_queue(1,1,8,8)