1. 程式人生 > >地牢逃脫-網易python(走迷宮BFS)

地牢逃脫-網易python(走迷宮BFS)

題目描述
給定一個 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次。
示例1
輸入

3 3



0 1
4
1 0
0 1
-1 0
0 -1

輸出
3

題意:
首先題目意思表述不清,真實意思應該是:從給定起點(一定為’.’),按照給定的若干跳躍(可以跨過障礙,但不可以落在’x’上),到達任意一個’.’的最小步驟次數集合中,選擇一個最大的!只要有一個’.’的點不能到達即視為無解,返回-1。

解析:
直接使用廣度優先搜尋(相當於樹的層次遍歷),通過使用佇列形式,將走過的路徑儲存為佇列,並將走過的路徑所在的路徑位置進行計數,用於計算最終的結果(即最遠距離)。

# 走迷宮-地牢逃脫(BFS-廣度優先搜尋、類似於樹的層次遍歷)

import queue

# 定義一個Point類,用於表示點的座標
class Point:
    x = 0
    y = 0

    def __init__(self,x,y):
        self.x = x
        self.y = y

    # 點的移動方向
    def go(self,index):
        return Point(self.x+direction[index][0],self.y+direction[index][1])

    # 所在的點是否可以移動(即既不在邊界外,也不是'X'標誌)
def isOk(self): if self.x>=0 and self.y>=0 and self.x<n and self.y<m and pointMap[self.x][self.y]=='.': return True else: return False n,m = map(int,input().split()) pointMap = [list(input()) for i in range(n)] x0,y0 = map(int,input().split()) k = int(input()) direction = [list(map(int,input().split())) for i in range(k)] # 初始化陣列vis,儲存位置是否可以通達,以及通過佇列儲存被第幾次訪問(記錄最大步數) # 其中0,表示不可通達 vis = [[0 for i in range(m)] for j in range(n)] start = Point(x0,y0) q = queue.Queue() q.put(start) # 廣度優先搜尋 while not q.empty(): temp = q.get() # 彈出隊頭元素(remove and get) for i in range(0,k): nextPoint = temp.go(i) # 下一個點合法且沒有走過(如果走過,則存在重複計數) if nextPoint.isOk() and vis[nextPoint.x][nextPoint.y]==0: vis[nextPoint.x][nextPoint.y] = vis[temp.x][temp.y] + 1 q.put(nextPoint) result = 0 route = True for i in range(n): for j in range(m): p = Point(i,j) # 尋找是否存在'.'的點無法到達,如果是,則返回-1(即設定為false) if vis[i][j]==0 and p.isOk(): # 由於起點初始為0,所以需要排除起點 if i == x0 and j == y0: continue else: route = False result = max(result,vis[i][j]) if route: print(result) else: print(-1)