맛있는물회

[맛있는물회] [파이썬] <백준 알고리즘> 6593번 "상범 빌딩" 본문

IT/알고리즘

[맛있는물회] [파이썬] <백준 알고리즘> 6593번 "상범 빌딩"

맛있는물회 2020. 6. 5. 13:14

문제 조건


당신은 상범 빌딩에 갇히고 말았다. 여기서 탈출하는 가장 빠른 길은 무엇일까? 상범 빌딩은 각 변의 길이가 1인 정육면체(단위 정육면체)로 이루어져있다. 각 정육면체는 금으로 이루어져 있어 지나갈 수 없거나, 비어있어서 지나갈 수 있게 되어있다. 당신은 각 칸에서 인접한 6개의 칸(동,서,남,북,상,하)으로 1분의 시간을 들여 이동할 수 있다. 즉, 대각선으로 이동하는 것은 불가능하다. 그리고 상범 빌딩의 바깥면도 모두 금으로 막혀있어 출구를 통해서만 탈출할 수 있다.

당신은 상범 빌딩을 탈출할 수 있을까? 만약 그렇다면 얼마나 걸릴까?

 

Input


입력은 여러 개의 테스트 케이스로 이루어지며, 각 테스트 케이스는 세 개의 정수 L, R, C로 시작한다. L(1 ≤ L ≤ 30)은 상범 빌딩의 층 수이다. R(1 ≤ R ≤ 30)과 C(1 ≤ C ≤ 30)는 상범 빌딩의 한 층의 행과 열의 개수를 나타낸다.

그 다음 각 줄이 C개의 문자로 이루어진 R개의 행이 L번 주어진다. 각 문자는 상범 빌딩의 한 칸을 나타낸다. 금으로 막혀있어 지나갈 수 없는 칸은 '#'으로 표현되고, 비어있는 칸은 '.'으로 표현된다. 당신의 시작 지점은 'S'로 표현되고, 탈출할 수 있는 출구는 'E'로 표현된다. 각 층 사이에는 빈 줄이 있으며, 입력의 끝은 L, R, C가 모두 0으로 표현된다. 시작 지점과 출구는 항상 하나만 있다.

 

Output


각 빌딩에 대해 한 줄씩 답을 출력한다. 만약 당신이 탈출할 수 있다면 다음과 같이 출력한다.

Escaped in x minute(s).

여기서 x는 상범 빌딩을 탈출하는 데에 필요한 최단 시간이다.

만일 탈출이 불가능하다면, 다음과 같이 출력한다.

Trapped!

 

생각한 아이디어


3차원 BFS 문제!

신박했다.

 

맨첨에는 그냥 BFS로 접근했는데 시간초과가 발생했다.

 

그래서 다익스트라로 다시 접근했더니 통과~

 

다익스트라의 기본 로직을 가지고 풀면 된다.

일반적인 동서남북의 BFS에 상하 방향 두개만 추가해주면 쉽게 풀리는 듯하다.

 

 

 

소스코드


#6593 상범 빌딩

import sys
from collections import deque
from heapq import heappop,heappush
input=sys.stdin.readline

INF=sys.maxsize

#동서남북상하
dz=[0,0,0,0,1,-1]
dy=[0,0,1,-1,0,0]
dx=[1,-1,0,0,0,0]

def bfs(start_z,start_y,start_x,end_z,end_y,end_x,MAP,l,r,c):
   heap=[]
   heappush(heap,(0,[start_z,start_y,start_x]))
   visited = [[[INF for _ in range(c)] for _ in range(r)] for _ in range(l)]
   visited[start_z][start_y][start_x]=0
   while heap:
      weight,pos=heappop(heap)
      z,y,x=pos[0],pos[1],pos[2]
      for dir in range(0,6):
         nz,ny,nx=z+dz[dir],y+dy[dir],x+dx[dir]
         if l>nz>=0 and r>ny>=0 and c>nx>=0 and MAP[nz][ny][nx]!='#':
            if visited[nz][ny][nx]>weight+1:
               visited[nz][ny][nx]=weight+1
               heappush(heap,(visited[nz][ny][nx],[nz,ny,nx]))

   return visited[end_z][end_y][end_x]

if __name__ == "__main__":
   while 1:
      l,r,c = map(int,input().split())
      if l==r==c==0: break
      MAP=[]
      start_z,start_y,start_x,flag=0,0,0,0
      end_z,end_y,end_x=0,0,0
      for i in range(0,l):
         level = [list(str(input().rstrip())) for _ in range(r)]
         if flag !=2:
            for j in range(0,r):
               for k in range(0,c):
                  if level[j][k]=='S':
                     start_z,start_y,start_x=i,j,k
                     flag+=1
                  elif level[j][k]=='E':
                     end_z,end_y,end_x=i,j,k
                     flag+=1
         tmp=input()
         MAP.append(level)
      

      ans = bfs(start_z,start_y,start_x,end_z,end_y,end_x,MAP,l,r,c)
      if ans==INF:
         print("Trapped!") 
      else:
         print("Escaped in %d minute(s)." %ans)


 

*파이썬 문법 정리

Comments