【算法】地牢逃脱

题目:给定一个 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)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章