题目:给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一些指定的步长遍历地牢,要求每一步都不可以超过地牢的边界,也不能到达障碍上。地牢的出口可能在任意某个可以通行的位置上。牛牛想知道最坏情况下,他需要多少步才可以离开这个地牢。
输入描述:每个输入包含 1 个测试用例。每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 50),表示地牢的长和宽。接下来的 n 行,每行 m 个字符,描述地牢,地牢将至少包含两个 '.'。接下来的一行,包含两个整数 x0, y0,表示牛牛的出发位置(0 <= x0 < n, 0 <= y0 < m,左上角的坐标为 (0, 0),出发位置一定是 '.')。之后的一行包含一个整数 k(0 < k <= 50)表示牛牛合法的步长数,接下来的 k 行,每行两个整数 dx, dy 表示每次可选择移动的行和列步长(-50 <= dx, dy <= 50) 输出描述:输出一行一个数字表示最坏情况下需要多少次移动可以离开地牢,如果永远无法离开,输出 -1。以下测试用例中,牛牛可以上下左右移动,在所有可通行的位置.上,地牢出口如果被设置在右下角,牛牛想离开需要移动的次数最多,为3次。 示例: 输入: 3 3 ... ... ... 0 1 4 1 0 0 1 -1 0 0 -1输出: 3
本题知识点:BFS迷宫问题
首先回顾一下BFS解决迷宫问题的算法。
BFS用队列的方法进行遍历搜索。 首先起始点入队,弹出(pop)起始点时,将起始点相邻的点入队,标记为已访问。接着,再按先入先出顺序弹出点,并将相邻点入队,以此类推,直至队列为空。即遍历完所有结点。
接着分析一下题目。抽象来看,就是一个迷宫问题。具体来看,
1)该迷宫大小、形状均为用户输入定义,有 “ . ” 的地方可以通过,没有点的地方不能通过;
2)移动步长用户输入定义;
3)初始位置用户输入
4)例外的就是,只要步长可达,不管中间是否断开,均可达,类似可以跳跃到达;
5)起始点到任意点,遵循最小路径原则,在所有最小路径中得到最大值;
6)最后写算法时注意一下边界以及是否被访问即可
所以在本题中,引入两个辅助二维数组,一是 visted 存储已经访问过的节点,保证访问的节点是未曾访问过的.;二是 path 存储初始点到每个节点的距离。这里用初始点到上一个点的距离值 +1 实现。 另外,在本题中,如果有节点无法被访问,则返回-1,这可以通过查看visited数组实现。最后取最大距离(如果无法访问,返回最大距离 -1)。
Python 代码如下:
#coding=utf-8
import copy
# obtain input
n,m = raw_input().strip().split()
lines =[]
for i in range(int(n)):
lines.append(raw_input().strip())
x,y = raw_input().strip().split()
k = raw_input().strip()
steps = []
for i in range(int(k)):
steps.append(raw_input().strip().split())
# parameters processing
n,m = int(n),int(m)
x,y = int(x),int(y)
k = int(k)
maze = []
# maze initialization
for i in range(n):
maze.append([])
for item in lines[i]:
if item == '.':
maze[i].append(0)
else:
maze[i].append(1)
# find minimal path
def DFS(maze,start,steps):
n,m = len(maze),len(maze[0])
queue = []
path = [[0 for i in range(m)] for j in range(n)]
visited = copy.deepcopy(maze)
queue.append(start)
visited[start[0]][start[1]] = 1
while queue:
x, y = int(queue[0][0]), int(queue[0][1])
for step in steps:
dn,dm = int(step[0]),int(step[1])
if x+dn>=0 and x+dn <n and y+dm>=0 and y+dm < m and visited[x+dn][y+dm]==0:
queue.append([x+dn,y+dm])
path[x+dn][y+dm] = path[x][y] + 1
visited[x+dn][y+dm] = 1
queue.pop(0)
val = max(max(val) for val in path)
for l in visited:
for item in l:
if item == 0 :
val = -1
break
print val
DFS(maze,[x,y],steps)