DFS+迷宫例题

DFS介绍+迷宫例题

深度优先搜索(Depth First Search简称DFS):以深度优先的一种遍历图或树的算法,何为以深度优先呢?核心思想就是一条路走到黑,当选定一个开始节点后,开始走一直走到不能继续后结束(此处与BFS相对,BFS广度优先搜索,同时开始进行搜索根节点的所有相邻节点,并依次往下,感兴趣的小伙伴可以去自行搜索查找),可以用栈(先进后出)来理解。
解释图
如图所示,以A为起始点按照深度优先的原则开始遍历,A->B->D->F->E->C。(此处只是举例,路径有很多种,遵循走相邻点的原则即可)。由A->B->D->F,因为F没有新的相邻点了,所以F可看做深度的最深处(一条路走到底了,可以回头了),此时由F返回D再走未走过的点E或C,完成遍历。
的思想来理解:
以A为起始点开始遍历,首先A入栈,A出栈的同时将与A相邻的B、C入栈,然后B出栈(C仍在栈里),与B相邻的进栈,与B相邻的是C、D,又因为C已经在栈里,所以D进栈,然后D出栈,与D相邻的C,E,F未进栈的进栈,所以E,F进栈,然后F出栈,至此,完全遍历一条路线。最后将栈中的剩余元素弹出,栈的特点是后进先出,所以先出E再出C。

问题描述
星球的一处迷宫游乐场建在某个小山坡上。它是由 10 ×10 相互连通的小房间组成的。
房间的地板上写着一个很大的字母。我们假设玩家是面朝上坡的方向站立,则:
L 表示走到左边的房间
R 表示走到右边的房间
U 表示走到上坡方向的房间
D 表示走到下坡方向的房间
星球的居民有点懒,不愿意费力思考。他们更喜欢玩运气类的游戏。这个游戏也是如此!
开始的时候,直升机把 100 名玩家放入一个个小房间内。玩家一定要按照地上的字母移
动。
迷宫地图如下:
UDDLUULRUL
UURLLLRRRU
RRUURLDLRD
RUDDDDUUUU
URUDLLRRUU
DURLRLDLRL
ULLURLLRDU
RDLULLRDDD
UUDDUDUDLL
ULRDLUURRR
请你计算一下,最后,有多少玩家会走出迷宫,而不是在里边兜圈子?
如果你还没明白游戏规则,可以参看下面一个简化的 4x4 迷宫的解说图
解释图
这是一道典型的DFS迷宫题,在此为了突出DFS易理解的逻辑,我先简单讲讲暴力算法的思路,暴力的话就采取依次遍历每个人要走的路径, 然后,用该题提供的行走规则来遍历每个人(根据"U"“D”“L”"F"来判断往哪边走)是利用了循环遍历的思想。暴力对新手其实是一个利器,如果不考虑超时问题的话,可以简化处理很多问题。
DFS则是运用递归思想,不仅在代码量上又大幅度优化,而且逻辑上更容易理解。所有地图上的点都已经标好,现在利用DFS递归不断走下去,如遇走不出去的用标记来标记(暴力算法亦然),每一个点调用dfs函数后都可以判断是走出去了还是在循环。
下面给出代码和详细解释

count=0
#创建地图
labyrinth=[[]for i in range(10)]
for i in range(10):
	labyrinth[i]=list(input())                    #按行读取后再用list转换,可以将题中给出的迷宫地图,一步到位传进来
vis = [[0 for i in range(10)]for i in range(10)]         #搜索指示标志,如果搜索过了标记为1,检查是否循环

#DFS
def dfs(i,j):          #接受参数,要搜索的点,返回该点的最终结果是出不去还是出去
if i<0 or i>9 or j<0 or j>9 :           #设置递归出口
    global count                                  #将count设置为global从而使count的值可以在函数中修改
    count+=1
else:
    if vis[i][j]:                              
        return
    vis[i][j]=1                      #标记点,如果走过则标记为1,若在该点(i,j)的递归处理中第二次走到同一个点,则证明该路径是循环的,不可能走出迷宫。
    if labyrinth[i][j] == "U":
        return dfs(i-1,j)
    if labyrinth[i][j] == "D":
        return dfs(i+1,j)
    if labyrinth[i][j] == "L":
        return dfs(i,j-1)
    if labyrinth[i][j] == "R":
        return dfs(i,j+1)
for p in range(10):
	for q in range(10):
    	vis = [[0 for i in range(10)]for i in range(10)]          #每次开始调用dfs时重置标记
    	dfs(p,q)
print(count)

让自己进入一片雪,一片叶,一片云,让自己平和安乐是一种修行。 —释一行

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值