算法题总结-迷宫问题
原题
https://www.nowcoder.com/practice/cf24906056f4488c9ddb132f317e03bc?tpId=37&tqId=21266&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3Fdifficulty%3D3%26page%3D1%26pageSize%3D50%26search%3D%26tpId%3D37%26type%3D37&difficulty=3&judgeStatus=undefined&tags=&title=
定义一个二维数组 N*M ,如 5 × 5 数组下所示:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。
数据范围:2≤n,m≤10,输入的内容只包含 0≤val≤1
输入描述:
输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。
输出描述:
左上角到右下角的最短路径,格式如样例所示。
输入示例
5 5
0 1 0 0 0
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出示例
(0,0)
(1,0)
(2,0)
(2,1)
(2,2)
(2,3)
(2,4)
(3,4)
(4,4)
解析:
核心在于回溯算法+广度优先遍历
回溯保证了可以记录已经找到的正确道路
广度优先遍历保证可以无遗漏
源码
import sys
count = 0
row=0
col=0
data = []
for line in sys.stdin:
a = line.split()
if count==0:
row,col = int(a[0]),int(a[1])
pass
else:
if count<=row:
data.append([int(item) for item in a])
pass
else:
break
pass
count+=1
# 回溯+广度优先
def getNeibor(data:list[list],i,j)->list:
out = []
if i>0 and data[i-1][j]==0:
out.append([i-1,j])
pass
if j>0 and data[i][j-1]==0:
out.append([i,j-1])
pass
if i<(row-1) and data[i+1][j]==0:
out.append([i+1,j])
pass
if j<(col-1) and data[i][j+1]==0:
out.append([i,j+1])
pass
return out
def recurisive(data:list[list],i,j,result:list)->list:
# 每次找出所有邻域对象
# 遍历所有邻域对象 找到终点就返回
# 如果遍历完还没到终点就返回异常
illegal = [-1]
neibor = getNeibor(data,i,j)
data[i][j] = 2
for item in neibor:
if item[0]==(row-1) and item[1]==(col-1):
result.append([item[0],item[1]])
return result
for item in neibor:
# 遍历每个邻域找到路就直接返回即可
tmp = data.copy()
tmp[item[0]][item[1]] = 2
out = result.copy()
out.append([item[0],item[1]])
itemOut = recurisive(tmp,item[0],item[1],out)
if -1 not in itemOut:
return itemOut
pass
return illegal
out = recurisive(data,0,0,[])
print("(0,0)")
for item in out:
print("("+str(item[0])+","+str(item[1])+")")
pass