Skip to content

Commit 220c29a

Browse files
committed
1 parent ec599bf commit 220c29a

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
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

Comments
 (0)