【算法】地牢逃脫

題目:給定一個 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)

 

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