1. 程式人生 > 其它 >CSP-I’m stuck!(Python實現100分)

CSP-I’m stuck!(Python實現100分)

技術標籤:CSP刷題python

問題描述
  給定一個R行C列的地圖,地圖的每一個方格可能是'#', '+', '-', '|', '.', 'S', 'T'七個字元中的一個,分別表示如下意思:
  '#': 任何時候玩家都不能移動到此方格;
  '+': 當玩家到達這一方格後,下一步可以向上下左右四個方向相鄰的任意一個非'#'方格移動一格;
  '-': 當玩家到達這一方格後,下一步可以向左右兩個方向相鄰的一個非'#'方格移動一格;
  '|': 當玩家到達這一方格後,下一步可以向上下兩個方向相鄰的一個非'#'方格移動一格;
  '.': 當玩家到達這一方格後,下一步只能向下移動一格。如果下面相鄰的方格為'#'
,則玩家不能再移動;   'S': 玩家的初始位置,地圖中只會有一個初始位置。玩家到達這一方格後,下一步可以向上下左右四個方向相鄰的任意一個非'#'方格移動一格;   'T': 玩家的目標位置,地圖中只會有一個目標位置。玩家到達這一方格後,可以選擇完成任務,也可以選擇不完成任務繼續移動。如果繼續移動下一步可以向上下左右四個方向相鄰的任意一個非'#'方格移動一格。   此外,玩家不能移動出地圖。   請找出滿足下面兩個性質的方格個數:   1. 玩家可以從初始位置移動到此方格;   2. 玩家不可以從此方格移動到目標位置。 輸入格式   輸入的第一行包括兩個整數R 和C,分別表示地圖的行和列數。(
1 ≤ R, C ≤ 50)。   接下來的R行每行都包含C個字元。它們表示地圖的格子。地圖上恰好有一個'S'和一個'T'。 輸出格式   如果玩家在初始位置就已經不能到達終點了,就輸出“I'm stuck!”(不含雙引號)。否則的話,輸出滿足性質的方格的個數。 樣例輸入 5 5 --+-+ ..|#. ..|## S-+-T ####. 樣例輸出 2 樣例說明   如果把滿足性質的方格在地圖上用'X'標記出來的話,地圖如下所示:   --+-+   ..|#X   ..|##   S-+-T   ####X

思路:先從S出發進行BFS,將訪問過的點在visited陣列中標記為1,然後再從T出發(如果S可以到達T的話)進行BFS,不過在遍歷周圍點的時候得用逆向思維(就是不是看這個點能不能到達周圍點,而是看周圍點能否到達這個點,如果能的話加入佇列),將遍歷過的點在visited陣列中標記為2,最後只需要統計visited中值為1的點的數量就行。


程式碼:

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

R,C = map(int,input().split())
maps = []
S_ind = [] # S的座標
T_ind = [] # T的座標
for i in range(R):
    temp = list(input())
    if 'S' in temp:
        x = i
        y = temp.index('S')
        S_ind.append(x)
        S_ind.append(y)
    if 'T' in temp:
        x = i
        y = temp.index('T')
        T_ind.append(x)
        T_ind.append(y)
    maps.append(temp)
_type = {
    'S':[[1,0],[-1,0],[0,1],[0,-1]],
    'T':[[1,0],[-1,0],[0,1],[0,-1]],
    '+':[[1,0],[-1,0],[0,1],[0,-1]],
    '-':[[0,1],[0,-1]],
    '|':[[1,0],[-1,0]],
    '.':[[1,0]]
}
# 用來計算上下左右四個點的座標
round_T = [[1,0],[-1,0],[0,1],[0,-1]]
visited = [[0]*C for i in range(R)] # 初始化

def bounds(x,y):
    if x>=0 and y >= 0 and x<R and y<C:
        return True
    else:
        return False
# 從S點出發遍歷
def BFS_S():
    flag = False  # 標記能不能到達目的地
    x = S_ind[0]
    y = S_ind[1]
    queue = []
    queue.append(Node(x,y))
    visited[x][y] = 1
    while queue:
        temp = queue.pop(0)
        x_t = temp.x
        y_t = temp.y
        c = maps[x_t][y_t]
        if c == 'T':
            flag = True
        if c != '#':
            t = _type[c]
            # 這個點周圍可以走的點
            for i in t:
                x_i = x_t + i[0]
                y_i = y_t + i[1]
                # 如果這個位置不是不能通行的,並且還沒有被訪問過
                if bounds(x_i,y_i) and maps[x_i][y_i] != '#' and visited[x_i][y_i] == 0:
                    visited[x_i][y_i] = 1
                    queue.append(Node(x_i,y_i))
    return flag
# 從T點出發遍歷
def BFS_T():
    x = T_ind[0]
    y = T_ind[1]
    queue = []
    queue.append(Node(x,y))
    visited[x][y] = 2
    while queue:
        temp = queue.pop(0)
        x_t = temp.x
        y_t = temp.y
        # 檢視這個點周圍 可以到達這個點的點
        for i in round_T:
            x_i = x_t + i[0]
            y_i = y_t + i[1]
            # 如果這個位置不是不能通行的,並且還沒有被訪問過
            if bounds(x_i,y_i) and maps[x_i][y_i] != '#' and visited[x_i][y_i] != 2:
                # 如果周圍點是+ 或者 S 那麼說明它上下左右都可以走,肯定能到達這個點的位置
                if maps[x_i][y_i] == '+' or maps[x_i][y_i] == 'S':
                    visited[x_i][y_i] = 2
                    queue.append(Node(x_i, y_i))
                # 如果周圍點是 . 那麼這個點必須在 . 的下方,因為 . 只能往下走
                elif maps[x_i][y_i] == '.':
                    if x_i+1 == x_t:
                        visited[x_i][y_i] = 2
                        queue.append(Node(x_i,y_i))
                elif maps[x_i][y_i] == '-' :
                    # 如果周圍點是 - 那麼在這個點必須在 - 的左方或者右方
                    if ((y_i-1 == y_t) or (y_i+1 == y_t)):
                        visited[x_i][y_i] = 2
                        queue.append(Node(x_i,y_i))
                # 如果周圍點是 | 那麼這個點必須在 | 的上方或者下方
                elif maps[x_i][y_i] == '|' :
                    if ((x_i-1 == x_t) or (x_i+1 == x_t)):
                        visited[x_i][y_i] = 2
                        queue.append(Node(x_i, y_i))
# 如果可到達目標點
if BFS_S():
    BFS_T()
    sum = 0
    for line in visited:
        sum += line.count(1)
    print(sum)
else:
    print("I'm stuck!")

提交結果圖:
提交結果