|
| 1 | +''' |
| 2 | +요구조건 |
| 3 | +1. 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다. |
| 4 | +하나의 토마토에 인접한 곳은 위, 아래, 왼쪽, 오른쪽, 앞, 뒤 여섯 방향에 있는 토마토를 의미한다. |
| 5 | +
|
| 6 | +
|
| 7 | +2. 토마토가 모두 익을 때까지 최소 며칠이 걸리는지를 계산해서 출력해야 한다. |
| 8 | +만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, |
| 9 | +토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다. |
| 10 | +
|
| 11 | +1. 아이디어 |
| 12 | +- 익은 토마토의 인접한 곳으로 그래프 탐색을 해야 하므로 bfs 사용. |
| 13 | +- 모든 토마토가 최소 몇 일에 익었는지 알기 위해서 토마토가 익은 일수를 저장해야 하므로 visited 배열에 저장. |
| 14 | +
|
| 15 | +2. 시간복잡도 |
| 16 | +- BFS의 시간복잡도는 O(V+E) V는 최대 1,000,000, E는 최대 6,000,000. 1초 안에 가능 |
| 17 | +
|
| 18 | +3. 구현 |
| 19 | +3-1. 입력받기 |
| 20 | +3-2. 초기 모든 토마토가 1 혹은 -1인지 확인. |
| 21 | +3-3. bfs 실행 |
| 22 | +3-4. 모두 1이 아닌데 bfs가 끝나면 -1 반환, 모두 1이면 visited 배열 중 가장 큰 값(최소 일수) 출력. |
| 23 | +
|
| 24 | +''' |
| 25 | + |
| 26 | +from collections import deque |
| 27 | +import sys |
| 28 | + |
| 29 | +inp = sys.stdin.readline |
| 30 | + |
| 31 | +# 가로, 세로, 높이 |
| 32 | +N, M, H = map(int, inp().strip().split()) |
| 33 | + |
| 34 | +arr = [] |
| 35 | +visited = [[[-1] * N for _ in range(M)] for _ in range(H)] |
| 36 | + |
| 37 | +# 입력받기 |
| 38 | +for _ in range(H): |
| 39 | + temp = [] |
| 40 | + for _ in range(M): |
| 41 | + temp.append(list(map(int, inp().strip().split()))) |
| 42 | + arr.append(temp) |
| 43 | + |
| 44 | +flag = False |
| 45 | +# 초기 익은 토마토들을 저장하는 배열 |
| 46 | +tomatoes = [] |
| 47 | + |
| 48 | +# 초기 모든 토마토가 1 혹은 -1인지 확인. |
| 49 | +for i in range(H): |
| 50 | + for j in range(M): |
| 51 | + for k in range(N): |
| 52 | + if arr[i][j][k] == 0: |
| 53 | + flag = True |
| 54 | + break |
| 55 | + if flag: |
| 56 | + break |
| 57 | + if flag: |
| 58 | + break |
| 59 | + |
| 60 | +# 초기 1인 토마토 저장 |
| 61 | +for i in range(H): |
| 62 | + for j in range(M): |
| 63 | + for k in range(N): |
| 64 | + if arr[i][j][k] == 1: |
| 65 | + tomatoes.append((i, j, k)) |
| 66 | + visited[i][j][k] = 0 |
| 67 | + |
| 68 | + |
| 69 | +def bfs(arr, visited, tomatoes): |
| 70 | + # 먼저 익은 토마토들로 큐 초기화 |
| 71 | + queue = deque(tomatoes) |
| 72 | + |
| 73 | + # 상 하 좌 우 위 아래 |
| 74 | + dx = [-1, 1, 0, 0, 0, 0] |
| 75 | + dy = [0, 0, -1, 1, 0, 0] |
| 76 | + dz = [0, 0, 0, 0, -1, 1] |
| 77 | + |
| 78 | + # bfs 탐색 |
| 79 | + while queue: |
| 80 | + (z, y, x) = queue.popleft() |
| 81 | + for idx in range(6): |
| 82 | + # 인접 칸으로 이동 |
| 83 | + new_z = z + dz[idx] |
| 84 | + new_y = y + dy[idx] |
| 85 | + new_x = x + dx[idx] |
| 86 | + |
| 87 | + # 조건 확인(1. 인접칸의 인덱스가 범위 안인지, 2. 인접칸이 안익은 토마토인지, 3. 인접칸이 방문한적 없는지) |
| 88 | + if (0 <= new_x < N and 0 <= new_y < M and 0 <= new_z < H) and (arr[new_z][new_y][new_x] == 0) and \ |
| 89 | + (visited[new_z][new_y][new_x] == -1): |
| 90 | + # 방문처리 |
| 91 | + queue.append((new_z, new_y, new_x)) |
| 92 | + arr[new_z][new_y][new_x] = 1 |
| 93 | + visited[new_z][new_y][new_x] = visited[z][y][x] + 1 |
| 94 | + |
| 95 | + # bfs가 끝났을 때, arr 배열에 0이 하나라도 있으면 -1 출력, 그렇지 않으면 visited 배열 요소 중 가장 큰 값 출력 |
| 96 | + if any(item == 0 for depth in arr for row in depth for item in row): |
| 97 | + print(-1) |
| 98 | + else: |
| 99 | + print(max(item for depth in visited for row in depth for item in row)) |
| 100 | + |
| 101 | + |
| 102 | +if flag: |
| 103 | + bfs(arr, visited, tomatoes) |
| 104 | +else: |
| 105 | + print(0) |
0 commit comments