目录
-
题目 信息
-
题目 答案
RRDDDDDDRRRRRRRRRDDLDDDLDLLLDDLLDDDLDDRDDRRDDLLLDDRDRDRRRRDRDRRRURURRURRUULUUULLUUUULLLUURRRRUUUULLULUUUUUUURUURRRRDDDRRDRRURRRRRRDRDDDDRRUURRURRDRDRDDDDDDDDDDDDRDDLDDDRRRDRRRRRRRURRDDDD
-
题目 思路
这个题目是我学习 广度优先搜索 之后做的第一个题目,想了的比较久,但是思路还是很清晰。
主要就是按照广度优先搜索的方法来,具体的思路都在我的另外一片博客里面有的:
从起点开始,建立一个队列,把从起点开始可以走的路都把ta加入到队列里面来,最后一定是可以找到出口的
建模的思路如下:
- 构建位置信息,将01的位置转换成具体的坐标,同时建立围墙,方便搜索
- 通过广度优先搜索的方法来找道路径
- 将路径转化成UDLR的方位信息,输出答案
-
题目 解析
import collections
#导入collections库,会用到其中deque模块(队列)
f=open("maze.txt","r")
#打开文件(该文件和py文件在同一目录下面,否则应当改成文件的绝对路径)
s=f.readlines()
#读取文件的所有行,形成一个列表,每一行为一个元素
#---------------------------------------------------------
position={}
#建立坐标位置对应0/1的字典
#先建围墙的坐标,由于1代表障碍,所以围墙设为1
for y_wall in range(0,32):
position[(0,y_wall)]='1'
position[(51,y_wall)]='1'
for x_wall in range(0,52):
position[(x_wall,0)]='1'
position[(x_wall,31)]='1'
y=1
#y位置的初始值
for y_position in s:
#遍历s中的每一行
for xy_index in range(len(y_position)-1):
#xy_index:0,1,2...49
position[(xy_index+1,y)]=y_position[xy_index]
#读取每一个0/1位置的坐标,将其加入到字典中去
y=y+1
#每读取一行之后,下一行y位置的值加1
#上面程序运行之后,01文件的每个点的坐标建立完毕,存储在字典position中
#---------------------------------------------------------
#下面开始对每个点开始搜索并且开始记录
m_deque=collections.deque()
#创建队列
start=(1,1)
end=(50,30)
checked_position=[]
#记录检查过的点的坐标信息的一个列表
m_deque.append(start)
#把起点加入到搜索队列中
while m_deque:
#只要队列不空,就继续搜索
to_check_position=m_deque.popleft()
#把队列的第一个位置拿出来检查
if to_check_position not in checked_position:
#如果这个点(坐标)没有被检查过
if to_check_position==end:
print("ok!")
break
#如果这个点为出口的点的坐标,那么输出ok,同时循环结束
else:
#否则循环继续
checked_position.append(to_check_position)
#记录已经检查过的坐标
up_position=(to_check_position[0],to_check_position[1]-1)
down_position=(to_check_position[0],to_check_position[1]+1)
left_position=(to_check_position[0]-1,to_check_position[1])
right_position=(to_check_position[0]+1,to_check_position[1])
#返回正在被检查的坐标的上下左右点位置的坐标
#不能用elif!!!!!!!!!!!!只能每个都是if
if position.get(up_position)=="0" and up_position not in checked_position:
m_deque.append(up_position)
#如果这个上面的点的坐标代表的是0,而且这个点坐标不在被检查过的列表里面,那么就把这个点的坐标位置加入到队列当中,下面同理
if position.get(down_position)=="0" and down_position not in checked_position:
m_deque.append(down_position)
if position.get(left_position)=="0" and left_position not in checked_position:
m_deque.append(left_position)
if position.get(right_position)=="0" and right_position not in checked_position:
m_deque.append(right_position)
all_line=checked_position+[end]
#这个all_line表示记录过的点,再加上出口这个点(就是说我这个程序从起点到终点它到过了什么地方,那么接下来就会通过这个列表找出迷宫的路)
#---------------------------------------------------------
#寻找出那条从起点到终点的路径
every_end=(end)
#寻找从终点开始,往前找
line=[]
#路径坐标的列表
line_dulr=[]
#路径上下左右方向的列表
while every_end!=start:
#只要找到的这个点不是起点,那么就继续找
up_xy=(every_end[0],every_end[1]-1)
down_xy=(every_end[0],every_end[1]+1)
left_xy=(every_end[0]-1,every_end[1])
right_xy=(every_end[0]+1,every_end[1])
#返回这个被找的点的上下左右的坐标信息
#注意这个下面必须要用elif!!!!!!!!!不能用都用if!!!!!!
if position.get(up_xy)=="0" and up_xy in all_line:
#如果这个点的上面点是0(表示可以走的路),而且这个点是被记录过的(表示这个点就是路径中的一个点)
index=all_line.index(up_xy)
#返回这个点在列表中的位置
all_line=all_line[:index]
#更新这个列表,就是说这个列表的最后一个元素是该点,那么下次再往前找位置的时候,眼光想起看就行了
line.append(up_xy)
#既然这个点是的话,那么就把这个点添加到最终的路径里面去
line_dulr.append("D")
#由于是反向走的,所以上面的这个坐标就要往下走
every_end = up_xy
#更新这个节点,然后从这个节点开始继续向前走
elif position.get(down_xy)=="0" and down_xy in all_line:
index=all_line.index(down_xy)
all_line=all_line[:index]
line.append(down_xy)
every_end=down_xy
line_dulr.append("U")
elif position.get(left_xy)=="0" and left_xy in all_line:
index=all_line.index(left_xy)
all_line=all_line[:index]
line.append(left_xy)
every_end=left_xy
line_dulr.append("R")
elif position.get(right_xy)=="0" and right_xy in all_line:
index=all_line.index(right_xy)
all_line=all_line[:index]
line.append(right_xy)
every_end=right_xy
line_dulr.append("L")
#print(line)
#路线的坐标
#print(line_dulr)
line_s=""
for i in line_dulr:
line_s=line_s+i
#把列表中的每个元素全都连接起来
print(line_s[::-1])
#输出答案,注意要反向一下,因为之前是倒着走的
-
题目 拓展
为了更加清晰的表达出,程序里面在从终点向起点找路径的那段代码里面有一个不用 if 而用 elif 的地方,我这里特别说明一下 if 和 elif 以及 if 和 if 连用的区别,下面的代码可以好形象表现出来:
if ---- if :
a=1
b=2
c=3
if a==1:
print("a")
if b==2:
print("b")
if c==3:
print("c")
#输出
a
b
c
if ---- elif :
a=1
b=2
c=3
if a==1:
print("a")
elif b==2:
print("b")
elif c==3:
print("c")
#输出
a
另外,我用海龟花了一下迷宫的图,方便大家直观感受(上下有点颠倒,但是不妨碍理解问题所在)
#海龟画迷宫
import turtle as t
t.hideturtle()
t.Turtle().screen.delay(0)
#快速画图,不然等的太久了
#画黑色的方块--围墙(障碍)
#为了更加清晰的表现出来,所有的位置或者什么尺寸都放大了十倍
def squure():
t.color('black')
t.begin_fill()
t.setheading(0)
t.fd(10)
t.setheading(270)
t.fd(10)
t.setheading(180)
t.fd(10)
t.setheading(90)
t.fd(10)
t.end_fill()
#画红色方块--路线
def squurered():
t.color('red')
t.begin_fill()
t.setheading(0)
t.fd(10)
t.setheading(270)
t.fd(10)
t.setheading(180)
t.fd(10)
t.setheading(90)
t.fd(10)
t.end_fill()
#画出迷宫的地图
for i in position:
if position.get(i)=="1":
t.penup()
t.goto(int(i[0])*10,int(i[1])*10)
t.pd()
squure()
#在迷宫中画出路线
for i in line:
t.penup()
t.goto(int(i[0])*10,int(i[1])*10)
t.pd()
squurered()
大家感受一下画出来的效果:
(正确的)代码中用的是 if 和 elif :
(错误的)代码中用的是 if 和 if :
有些地方多走了
要是代码中有什么问题,或是没有理解的部分欢迎大家在下面评论,或者是私信我!