python与矩阵探路(DFS)的麻烦
我对DFS遇到问题,可能是在面对墙时来自递归中的问题。
它不是不断地进行只能导致墙壁的尝试,而应返回其先前的位置并尝试另一条路径。
,它严重依靠尝试的尝试(N,S,E,W或其他组合)
此外
def portal(M,l,c): # locates current portal and changes position (if entering portal 1, go to portal 2)
for elem in D.keys():
x = 1
if elem == M[l][c]:
if [l,c] == D[elem][0] and x: [l,c] = D[elem][1]; x -=1
if [l,c] == D[elem][1] and x: [l,c] = D[elem][0]; x-=1
return [l,c]
def dfs(Q,p):
l, c = Q[-1] # previous position
if [l,c] == COORD: return True
for dir in [(l-1, c,1), (l, c - 1,2), (l , c+1,3), (l+1 ,c,4)]: # dir = (l,c,p) = next row, next column and a number that represents the direction taken (1 = north)
j=1
if p:
if dir[2] == p: # if passing through a portal, p should not update, or else it would attempt to move in a direction it's not intended to
nextl,nextc = dir[:2]
print(nextl,nextc,l,c)
else: j = 0 # p is not 0 and no move happens (j = 0)
else: # if no portal has been used: try all possible directions
nextl, nextc, p = dir
if j:
if len(M[0]) > c >= 0 and 0 <= l < len(M): # if inbounds
if M[nextl][nextc] in D: # if the next move lands in a portal, change coordinates using the function portal()
Q.append((nextl,nextc))
nextl,nextc = portal(M,nextl,nextc)
if M[nextl][nextc] and ((nextl, nextc) not in Q) and (M[nextl][nextc] not in D):
# if there is no wall on the next position and it has not been visited yet, call dfs again for the next position
Q.append((nextl, nextc))
if dfs(Q,0):
return True
else:
Q.pop()
elif M[nextl][nextc] and (M[nextl][nextc] in D) and ((nextl, nextc) not in Q):
# if a portal has been used, the next move should keep previous p (direction). Therefore, the function call is different, to prevent it from attempting to move in all 4 directions.
Q.append((nextl,nextc))
if dfs(Q,p):
return True
else:
Q.pop()
elif M[l][c] not in D: p = 0
# resets p if no move is possible ( allows it to gain a new direction from the for loop above)
else: p = 0
M = [];L = int(input())
for _ in range(L): M.append(input().split()) # Matrix input
for i in M:
for h in i:
if h == "#": M[M.index(i)][i.index(h)] = 0
elif h == ".": M[M.index(i)][i.index(h)] = 1 # Replaces path with 1 (easier to write)
l0, c0 = (int(i) for i in input().split())
queue = [(l0, c0)] # initial position
COORD = 0
D={};lineP=-1
for LINE in M: # locates portals and assigns to the corresponding letter both coordinates
colP = -1; lineP+=1
for COL in LINE:
colP+=1
if COL not in ["*",0,1]:
if COL in D: D[COL].append([lineP,colP])
else: D[COL] = [[lineP,colP]]
if COL == "*": COORD=[lineP,colP] # locates the destination (marked with "*")
if dfs(queue,0):
print("Success"
else:
print("Failure")
I am having issues with dfs, probably from a RecursionError when facing a wall.
Instead of continuously running an attempt which can only lead to a wall, it is supposed to return to its previous position and try another path.
Also, it leans heavily on the order in which attempts are made (N,S,E,W or other combinations)
Thanks in advance
def portal(M,l,c): # locates current portal and changes position (if entering portal 1, go to portal 2)
for elem in D.keys():
x = 1
if elem == M[l][c]:
if [l,c] == D[elem][0] and x: [l,c] = D[elem][1]; x -=1
if [l,c] == D[elem][1] and x: [l,c] = D[elem][0]; x-=1
return [l,c]
def dfs(Q,p):
l, c = Q[-1] # previous position
if [l,c] == COORD: return True
for dir in [(l-1, c,1), (l, c - 1,2), (l , c+1,3), (l+1 ,c,4)]: # dir = (l,c,p) = next row, next column and a number that represents the direction taken (1 = north)
j=1
if p:
if dir[2] == p: # if passing through a portal, p should not update, or else it would attempt to move in a direction it's not intended to
nextl,nextc = dir[:2]
print(nextl,nextc,l,c)
else: j = 0 # p is not 0 and no move happens (j = 0)
else: # if no portal has been used: try all possible directions
nextl, nextc, p = dir
if j:
if len(M[0]) > c >= 0 and 0 <= l < len(M): # if inbounds
if M[nextl][nextc] in D: # if the next move lands in a portal, change coordinates using the function portal()
Q.append((nextl,nextc))
nextl,nextc = portal(M,nextl,nextc)
if M[nextl][nextc] and ((nextl, nextc) not in Q) and (M[nextl][nextc] not in D):
# if there is no wall on the next position and it has not been visited yet, call dfs again for the next position
Q.append((nextl, nextc))
if dfs(Q,0):
return True
else:
Q.pop()
elif M[nextl][nextc] and (M[nextl][nextc] in D) and ((nextl, nextc) not in Q):
# if a portal has been used, the next move should keep previous p (direction). Therefore, the function call is different, to prevent it from attempting to move in all 4 directions.
Q.append((nextl,nextc))
if dfs(Q,p):
return True
else:
Q.pop()
elif M[l][c] not in D: p = 0
# resets p if no move is possible ( allows it to gain a new direction from the for loop above)
else: p = 0
M = [];L = int(input())
for _ in range(L): M.append(input().split()) # Matrix input
for i in M:
for h in i:
if h == "#": M[M.index(i)][i.index(h)] = 0
elif h == ".": M[M.index(i)][i.index(h)] = 1 # Replaces path with 1 (easier to write)
l0, c0 = (int(i) for i in input().split())
queue = [(l0, c0)] # initial position
COORD = 0
D={};lineP=-1
for LINE in M: # locates portals and assigns to the corresponding letter both coordinates
colP = -1; lineP+=1
for COL in LINE:
colP+=1
if COL not in ["*",0,1]:
if COL in D: D[COL].append([lineP,colP])
else: D[COL] = [[lineP,colP]]
if COL == "*": COORD=[lineP,colP] # locates the destination (marked with "*")
if dfs(queue,0):
print("Success"
else:
print("Failure")
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我创建了一个可以找到可以达到
目标
的路径的脚本。如果路径不存在,它将打印任务是不可能的。注意:该算法并未寻求所有可能的路径。一旦找到一个,它就会返回那条路。因此,它不会将最短的目标返回目标。如果存在,它将返回一条路径。否则,它将返回一个空列表。
dfs_pathfinder
的返回是布尔值,说明是否找到了路径。要检索路径,请将列表存储到路径
,然后通过参考将列表填充为参数。我试图使用注释来解释脚本的每一行。如果您不了解某些内容或从中得到意外的错误,请随时将其发布在此答案的评论中。
该脚本从文件中获取输入。在这种情况下,
file.txt
,其中的内容是:测试脚本后,我得到了此输出:
启动位置为
0
位置,14 < /代码>是
目标
。图块10
和11
都是门户网站t
的两端,它告诉算法使用门户网站t
要达到目标
。I created a script that finds one path that can reach
goal
. If the path does not exists, it prints that the task is impossible.Note: the algorithm does not seek for all possible paths. Once it finds one, it returns that path. Consequently, it does not return the shortest path to goal. It returns a path, if it exists. Otherwise, it returns an empty list.
The return of
dfs_pathfinder
is a boolean, telling if the path was found or not. To retrive the path, store a list topath
, and let the function fill the list passed as parameter by reference.I tried to explain every single line of the script using comments. If you didn't understood something, or got an unexpected bug from it, feel free to post it on the comments of this answer.
The script gets input from a file. In this case,
file.txt
, which contents are:After testing the script, I got this output:
The starting position is at
0
position, and14
is thegoal
. The tiles10
and11
are both ends of the portalT
, which tells that the algorithm used the portalT
to reach thegoal
.