[BOJ] Q3055 탈출

Question

Language: Python

Difficulty: Gold 4

해당 문제는 4179와 유사한 방식으로 문제를 풀이하면 된다.

bfs 1: 물의 이동

#물의 이동 수행
visited=[[False] * n_cols for _ in range(n_rows)]
while water_queue:
    row,col,time=water_queue.popleft()
    
    #이전에 방문한 경우
    if visited[row][col]:
        continue
    visited[row][col]=True
    #물이 해당 좌표에 도달하는 시간
    time_map[row][col]=time
    

    for dir in range(4):
        next_row=row+dy[dir]
        next_col=col+dx[dir]
        #범위를 넘어서는 경우
        if next_row < 0 or next_row>=n_rows or next_col<0 or next_col>=n_cols:
            continue
        #다음 좌표가 돌인 경우
        if board[next_row][next_col]=="X":
            continue
        #물은 목적지 좌표에 도달할 수 없다.
        if board[next_row][next_col]=="D":
            continue

        water_queue.append((next_row,next_col,time+1))

매분 마다 동시에 이동하기 때문에, 우선적으로 물을 먼저 이동시켜서 각 칸에 대해 물이 언제 도착하는 지에 대해 bfs를 실행한다.

bfs 2: 고슴도치의 이동

#고슴도치의 이동 수행
visited=[[False] * n_cols for _ in range(n_rows)]
while animal_queue:
    row,col,time=animal_queue.popleft()
    #목적지에 도달한 경우
    if (row,col)==(end_row,end_col):
        print(time)
        return
    #이전에 방문한 경우
    if visited[row][col]:
        continue
    visited[row][col]=True

    for dir in range(4):
        next_row=row+dy[dir]
        next_col=col+dx[dir]
        #범위를 벗어나는 경우
        if next_row < 0 or next_row>=n_rows or next_col<0 or next_col>=n_cols:
            continue
        #다음 좌표가 돌인 경우
        if board[next_row][next_col]=="X":
            continue
        
        #해당 자리에 물이 먼저 도착하는 경우에는 다음 좌표로 이동 불가능
        if time_map[next_row][next_col] <= time+1:
            continue
        animal_queue.append((next_row,next_col,time+1))

물의 이동을 먼저 수행한 다음, 고슴도치를 이동시킨다. 이때, 고슴도치가 해당 칸에 도착하는 시간과 물이 도착하는 시간을 비교해서 물이 먼저 도착하는 경우에는 고슴도치가 해당 칸으로 이동이 불가능하다.

Solution

from collections import deque
from math import inf
def solution():
    time_map=[[inf] * n_cols for _ in range(n_rows)]
    end_row,end_col=0,0
    water_queue,animal_queue=deque(),deque()
    dy=[-1,0,1,0]
    dx=[0,1,0,-1]

    
    for row in range(n_rows):
        for col in range(n_cols):
            #출발점
            if board[row][col]=="S":
                animal_queue.append((row,col,0))
            #도착점
            if board[row][col]=="D":
                end_row,end_col=row,col
            #물이 있는 자리의 좌표
            if board[row][col]=="*":
                water_queue.append((row,col,0))
    
    #물의 이동 수행
    visited=[[False] * n_cols for _ in range(n_rows)]
    while water_queue:
        row,col,time=water_queue.popleft()
        
        #이전에 방문한 경우
        if visited[row][col]:
            continue
        visited[row][col]=True
        #물이 해당 좌표에 도달하는 시간
        time_map[row][col]=time
        

        for dir in range(4):
            next_row=row+dy[dir]
            next_col=col+dx[dir]
            #범위를 넘어서는 경우
            if next_row < 0 or next_row>=n_rows or next_col<0 or next_col>=n_cols:
                continue
            #다음 좌표가 돌인 경우
            if board[next_row][next_col]=="X":
                continue
            #물은 목적지 좌표에 도달할 수 없다.
            if board[next_row][next_col]=="D":
                continue

            water_queue.append((next_row,next_col,time+1))
    
    #고슴도치의 이동 수행
    visited=[[False] * n_cols for _ in range(n_rows)]
    while animal_queue:
        row,col,time=animal_queue.popleft()
        #목적지에 도달한 경우
        if (row,col)==(end_row,end_col):
            print(time)
            return
        #이전에 방문한 경우
        if visited[row][col]:
            continue
        visited[row][col]=True

        for dir in range(4):
            next_row=row+dy[dir]
            next_col=col+dx[dir]
            #범위를 벗어나는 경우
            if next_row < 0 or next_row>=n_rows or next_col<0 or next_col>=n_cols:
                continue
            #다음 좌표가 돌인 경우
            if board[next_row][next_col]=="X":
                continue
            
            #해당 자리에 물이 먼저 도착하는 경우에는 다음 좌표로 이동 불가능
            if time_map[next_row][next_col] <= time+1:
                continue
            animal_queue.append((next_row,next_col,time+1))

    print("KAKTUS")


if __name__ == "__main__":
    n_rows,n_cols=map(int,input().split())
    board=[list(input().strip()) for _ in range(n_rows)]
                
    solution()

댓글남기기