小强在玩一个走迷宫的游戏,他操控的人物现在位于迷宫的起点,他的目标是尽快的达到终点。每一次他可以选择花费一个时间单位向上或者向下或者向左或者向右走一格,或是使用自己的对称飞行器花费一个时间单位瞬移到关于当前自己点中心对称的格子,且每一次移动的目的地不能存在障碍物。具体来数说,设当前迷宫有n行m列,如果当前小强操控的人物位于点A(x, y),那么关于点A中心对称的格子B(x’, y’)满足x + x’ = n + 1且 y + y’ = m + 1。需要注意的是,对称飞行器最多使用5次。
输入描述:
第一行两个空格分隔的正整数n,m,分别代表迷宫的行数和列数。
接下来n行,每行一个长度为m的字符串来描述这个迷宫。
其中 .代表通路。 #代表障碍。 S代表起点。 E代表终点。 保证只有一个S和一个E。
2 <= n, m <= 500
输出描述:
仅一行一个整数表示从起点最小花费多少时间单位到达终点。
如果无法到达终点,输出-1。
由于要求最短的路径,个人认为BFS比较适合,BFS搜索到的第一个解一定是最优解。(在普通的广度优先算法里面,走过的节点就不会再走,由于本题加入了飞行次数,所以我认为走过的节点有可能需要再走一次,比如第一次走过这个节点的时候没有了飞行次数,而第二走过这个节点的时候还有一次飞行次数,那么第一次可能找不到解,第二次就可能找到)。于是加入了一个点飞行次数的记录,然后第二次走某个节点时如果飞行次数比第一次多,那么就表示可以再走
代码
import sys
from collections import deque
import copy
class node:
def __init__(self, x, y, stp, cnt):
self.x = x
self.y = y
self.stp = stp
self.cnt = cnt
def check(x, y, m, n):
if x>=0 and x<n and y>=0 and y<m:
return True
else:
return False
dir = [[0,1], [0,-1], [1,0], [-1,0]]
def BFS(sx, sy, ex, ey, n, m, map):
q = deque()
st = node(sx, sy, 0, 5)
vis = []
for i in range(n):
vis.append([])
for j in range(m):
vis[i].append(0)
fly_count = []
for i in range(n):
fly_count.append([])
for j in range(m):
fly_count[i].append(0)
vis[sx][sy] = 1
q.append(st)
while q:
now = q.popleft()
if now.x == ex and now.y == ey:
return now.stp
for i in range(4):
nxt = copy.deepcopy(now)
nxt.x = now.x + dir[i][0]
nxt.y = now.y + dir[i][1]
nxt.stp = now.stp + 1
nxt.cnt = now.cnt
if check(nxt.x, nxt.y, m, n) and (vis[nxt.x][nxt.y]==0 or vis[nxt.x][nxt.y]==1 and nxt.cnt>fly_count[nxt.x][nxt.y]) and (map[nxt.x][nxt.y]=='.' or map[nxt.x][nxt.y]=='E'):
vis[nxt.x][nxt.y] = 1
fly_count[nxt.x][nxt.y] = nxt.cnt
q.append(nxt)
if now.cnt >= 1:
nxt = copy.deepcopy(now)
nxt.x = n-1 - now.x
nxt.y = m-1 - now.y
nxt.stp = now.stp + 1
nxt.cnt = now.cnt - 1
if check(nxt.x, nxt.y, m, n) and (vis[nxt.x][nxt.y]==0 or vis[nxt.x][nxt.y]==1 and nxt.cnt>fly_count[nxt.x][nxt.y]) and (map[nxt.x][nxt.y]=='.' or map[nxt.x][nxt.y]=='E'):
vis[nxt.x][nxt.y] = 1
fly_count[nxt.x][nxt.y] = nxt.cnt
q.append(nxt)
return -1
if __name__=='__main__':
map = [['#', 'S', '.', '.'], ['E', '#', '.', '.'],['#', '.', '.', '.'],['.', '.', '.', '.']]
n = 4
m = 4
for i in range(len(map)):
for j in range(len(map[0])):
if map[i][j] == 'S':
sx = i
sy = j
if map[i][j] == 'E':
ex = i
ey = j
nxt = node(0,0,0,0)
print(BFS(sx, sy, ex, ey, n, m, map))