1+ """
2+
3+
4+
5+ """
6+
7+ def myprint_3d (arr3 ) :
8+ for arr in arr3 :
9+ for lst in arr :
10+ print (* lst )
11+ print ()
12+ print ()
13+
14+ def myprint_2d (arr ):
15+ for lst in arr :
16+ print (* lst )
17+ print ()
18+
19+ # sk_3d ,si_3d, sj_3d = find_3d_start()
20+ def find_3d_start (): # 3d 출발 지점 좌표
21+ for i in range (M ) :
22+ for j in range (M ) :
23+ if arr3 [4 ][i ][j ]== 2 :
24+ return 4 , i , j
25+
26+ def find_2d_end (): # 2d에서 최종 도착 지점
27+ for i in range (N ):
28+ for j in range (N ) :
29+ if arr [i ][j ] == 4 :
30+ arr [i ][j ] = 0
31+ return i , j
32+
33+ def find_3d_base (): # 전체 맵에서 3d 영역 시작(절대)좌표 - 좌측 상단
34+ for i in range (N ) :
35+ for j in range (N ) :
36+ if arr [i ][j ] == 3 :
37+ return i , j
38+
39+ # 3d 차원 & 2d 시작 위치 (텔레포트) 좌표 반환
40+ # 3d : 상대 좌표 -> 2d 전체 맵 절대 좌표
41+ def find_3d_end_2d_start ():
42+ #[1] 3차원 시작 좌표(base) 찾기 =3 등장 -> 좌측상단
43+ bi , bj = find_3d_base ()
44+
45+ #[2] 3차원 좌표에서 2d 차원 연결 좌표 찾기 (1차 목적지 in 3d )
46+ # i,j : 2d 전체 맵 기준
47+ # si ,sj = 2d통로 = 3d 통로 : (ek,ei,ej)
48+ for i in range (bi , bi + M ) :
49+ for j in range (bj , bj + M ) :
50+ if arr [i ][j ]!= 3 : # 3차원 위치 아니면 skip
51+ continue
52+
53+ # 1차 출구 : 3d 차원에서 ->2d 로 텔레포트 하는 위치
54+ if arr [i ][j + 1 ] == 0 : # 우측에 3d - 2d 탈출구 (3차원 우측으로 1차 출구)
55+ return 0 , M - 1 , (M - 1 )- (i - bi ) , i , j + 1 # ek(평면) = 0 동쪽 , ei = M-1 , ej = i , si = i , sj = j+1
56+ elif arr [i ][j - 1 ] == 0 : # 좌측 1차 출구
57+ return 1 , M - 1 , i - bi , i , j - 1 # ek(평면)=1, ei=M-1, ej=i, si=i, sj=j+1
58+ elif arr [i + 1 ][j ]== 0 : # 아래쪽 1차 출구
59+ return 2 , M - 1 , j - bj , i + 1 ,j # ek(평면)=2, ei=M-1, ej=i, si=i, sj=j+1
60+ elif arr [i - 1 ][j ] == 0 : # 위쪽에 1차 출구
61+ return 3 ,M - 1 , (M - 1 )- (j - bj ) , i - 1 , j # ek(평면)=3, ei=M-1, ej=i, si=i, sj=j+1
62+ #여기까지 올릴 없지만
63+ return - 1
64+
65+ from collections import deque
66+ # dist = bfs_3d(sk_3d ,si_3d, sj_3d ,ek_3d , ei_3d,ej_3d)
67+
68+ left_nxt = {0 :2 , 2 :1 , 1 :3 , 3 :0 }
69+ right_nxt = {0 :3 , 2 :0 , 1 :2 , 3 :1 }
70+
71+ def bfs_3d (sk ,si , sj ,ek , ei ,ej ):
72+ q = deque ()
73+ v = [[[0 ]* M for _ in range (M )] for k in range (5 ) ] # 방문 여부 + 최소 거리
74+
75+ q .append ((sk , si , sj ))
76+ v [sk ][si ][sj ] = 1
77+
78+ while q :
79+ ck ,ci , cj = q .popleft ()
80+
81+ # 목적지 도달
82+ if (ck ,ci ,cj ) == (ek ,ei , ej ) :
83+ return v [ck ][ci ][cj ]
84+
85+
86+ # 4방향, 범위내/ 범위 밖 -> 다른 k 로 이동 처리 , 미방문
87+ for di ,dj in ((- 1 ,0 ) ,(1 ,0 ), (0 ,- 1 ), (0 ,1 )):
88+ ni , nj = ci + di , cj + dj
89+ # 범위 밖으로 이동- > 다른 k 평면으로 이동
90+ if ni < 0 : #(1) 위쪽 범위 밖 이탈
91+ if ck == 0 : nk , ni , nj = 4 , (M - 1 )- cj , M - 1
92+ elif ck == 1 : nk ,ni , nj = 4 , cj , 0
93+ elif ck == 2 : nk , ni , nj = 4 , M - 1 , cj
94+ elif ck == 3 : nk , ni ,nj = 4 ,0 ,(M - 1 )- cj
95+ elif ck == 4 : nk , ni , nj = 3 , 0 ,(M - 1 )- cj
96+ elif ni >= M : #(2) 아래쪽으로 범위 이탈
97+ if ck == 4 : nk , ni , nj = 2 , 0 , cj
98+ else : continue
99+ elif nj < 0 : # (3) 왼쪽 범위 이탈
100+ if ck == 4 : nk , ni , nj = 1 , 0 , ci
101+ else :
102+ nk , ni , nj = left_nxt [ck ], ci , M - 1
103+ elif nj >= M : # (4) 오른쪽 범위 이탈
104+ if ck == 4 : nk , ni , nj = 0 , 0 , (M - 1 )- ci
105+ else :
106+ nk , ni , nj = right_nxt [ck ] , ci , 0
107+ else : # (5) 범위 내
108+ nk = ck
109+ # 미방문 , 조건 맞으면
110+ if v [nk ][ni ][nj ] == 0 and arr3 [nk ][ni ][nj ] == 0 :
111+ q .append ((nk ,ni ,nj ))
112+ v [nk ][ni ][nj ] = v [ck ][ci ][cj ]+ 1
113+ # 여긴 경로 없음
114+ return - 1
115+ # dist = bfs_2d(v , dist ,si,sj, ei , ej )
116+ def bfs_2d (v , dist ,si ,sj , ei , ej ):
117+ q = deque ()
118+
119+ q .append ((si ,sj ))
120+ v [si ][sj ] = dist
121+
122+ while q :
123+ ci ,cj = q .popleft ()
124+ if (ci ,cj ) == (ei ,ej ):
125+ return v [ci ][cj ]
126+ # 네방향, 범위내, (미방문)/조건맞으면(길이고, v[ci][cj]+1<v[ni][nj] - 최단 거리)
127+ for di ,dj in ((- 1 ,0 ),(1 ,0 ),(0 ,- 1 ),(0 ,1 )):
128+ ni ,nj = ci + di , cj + dj
129+ if 0 <= ni < N and 0 <= nj < N and arr [ni ][nj ]== 0 and v [ci ][cj ]+ 1 < v [ni ][nj ]:
130+ q .append ((ni ,nj ))
131+ v [ni ][nj ]= v [ci ][cj ]+ 1
132+
133+ return - 1
134+ ##########
135+ ########
136+ #1. 입력변수 - 공간 한변의 길이N , 시간의 벽 한 변의 길이M, 시간 이상 현상 개수 F 공백
137+ N ,M ,F = map (int , input ().split ())
138+ arr = [list (map (int , input ().split ())) for _ in range (N )]
139+ arr3 = [ [list (map (int , input ().split ())) for _ in range (M )] for k in range (5 ) ]
140+ wall = [ list (map (int , input ().split ())) for _ in range (F )] # 시간 이상 : 초기위치 (r,c) , 확산 방향 d, 확산 상수 v
141+
142+ # [1] 주요 위치 찾기
143+ # 3d 의 시작 , 3차원 끝(탈출) , 2차원 시작 , 2차원 끝 좌표 탐색
144+ sk_3d ,si_3d , sj_3d = find_3d_start ()
145+ ei , ej = find_2d_end () # 3d 출구(1차 도착지점) 좌표
146+ ek_3d , ei_3d ,ej_3d , si ,sj = find_3d_end_2d_start () # 3d 출구(1차 도착지점) 랑 2d 시작점
147+ # print(f"1111111111111111")
148+ # print(sk_3d ,si_3d, sj_3d )
149+ # print(ei , ej )
150+ # print(ek_3d , ei_3d,ej_3d , si,sj)
151+
152+ #[2] 3차원 공간 탐색 : 시작 위치 -> 탈출 위치거리 탐색(BFS 최단거리)
153+ dist = bfs_3d (sk_3d ,si_3d , sj_3d ,ek_3d , ei_3d ,ej_3d )
154+ # 동 서 남 북
155+ di = [ 0 , 0 , 1 ,- 1 ]
156+ dj = [ 1 ,- 1 , 0 , 0 ]
157+ if dist != - 1 : # 3d 탈출 불가능
158+ #[3] 2차원 탐색 준비 : 시간 이상 현상 처리해서 v 에 시간 표시 : BFS 확산시 v 배수보다 작으면 통과 표시
159+ # value: 이상 현상이 발생하는 time
160+ v = [[401 ]* N for _ in range (N )]
161+
162+ for wi , wj , wd ,wv in wall : # 이상 현상 초기 위치 , 확산 방향 , 확산 상수
163+ v [wi ][wj ] = 1
164+ for mul in range (1 , N + 1 ) :
165+ wi ,wj = wi + di [wd ] , wj + dj [wd ] # 다음 확산될 곳
166+ if 0 <= wi < N and 0 <= wj < N and arr [wi ][wj ] == 0 and (wi ,wj )!= (ei ,ej ) : # wv 단위로 wd 방향으로 확산표시(출구가 아닌 경우)
167+ if v [wi ][wj ] > wv * mul : # 더 큰값일때만 갱신(겹칠 수 있음)
168+ v [wi ][wj ] = wv * mul
169+ else :
170+ break
171+
172+ #[4] 2차원 시작 위치에서 BFS로 탈출구 탐색
173+ dist = bfs_2d (v , dist ,si ,sj , ei , ej )
174+ print (dist )
0 commit comments