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