Algorithm

[BOJ] 7569번 토마토 - Python

lerrybe 2023. 7. 14. 00:58

문제

 

7569번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100,

www.acmicpc.net

 

 

풀이

  • 처음에 익을 수 없는 경우의 수를 먼저 체크해주는 것이 좋겠다고 생각했다. 
  • 이번에는 큐에 넣어주어야 하는 경우가 두 가지 더 추가되었었다. (위층, 아래층)
  • 예외적인 상황은 먼저 이른 리턴해주어서 가지치는 것도 특정 케이스에서 복잡도를 줄이는 방법 중 하나 인 것 같다.
from collections import deque


# TODO: 토마토가 익는 최소 일 수 구하기 🪀
def solution(h, n, m, board):
    if check_already_ripen(h, n, m, board):  # 초기 검증
        return 0

    visited = [[[False] * m for _ in range(n)] for _ in range(h)]
    days = bfs(visited, board, n, m, h)

    if check_impossible_to_ripen(h, n, m, board):  # 검증
        return -1
    return days


def bfs(visited, board, n, m, h):
    day = 0
    dv = [0, 0, 0, 0, 1, -1]
    dr = [0, 0, 1, -1, 0, 0]
    dc = [1, -1, 0, 0, 0, 0]
    queue = deque()
    for c in range(m):
        for r in range(n):
            for v in range(h):
                if not visited[v][r][c] and board[v][r][c] == 1:  # 현재 익어 있어야만 영향 끼칠 수 있음
                    queue.append((v, r, c, 0))
                    visited[v][r][c] = True

    while queue:
        v, r, c, day = queue.popleft()
        for i in range(6):
            nv = v + dv[i]
            nr = r + dr[i]
            nc = c + dc[i]
            if nr < 0 or nr >= n or nc < 0 or nc >= m or nv >= h or nv < 0:
                continue
            if visited[nv][nr][nc] or board[nv][nr][nc] != 0:
                continue
            queue.append((nv, nr, nc, day + 1))
            visited[nv][nr][nc] = True
            board[nv][nr][nc] = 1
    return day


def check_already_ripen(h, n, m, board):
    num_tomato = 0
    for c in range(m):
        for r in range(n):
            for v in range(h):
                if board[v][r][c] == 1 or board[v][r][c] == -1:
                    num_tomato += 1
    if num_tomato == n * m * h:
        return True
    return False


def check_impossible_to_ripen(h, n, m, board):
    for c in range(m):
        for r in range(n):
            for v in range(h):
                if board[v][r][c] == 0:
                    return True
    return False


M, N, H = map(int, input().split())
board = [[list(map(int, input().split())) for _ in range(N)] for _ in range(H)]
print(solution(H, N, M, board))

'Algorithm' 카테고리의 다른 글

[알고리즘] 재귀 (Recursion)  (0) 2023.07.14
[BOJ] 1697번 숨바꼭질 - Python  (0) 2023.07.14
[BOJ] 10026번 적록색약 - Python  (0) 2023.07.14
[BOJ] 2504번 괄호의 값 - Python  (0) 2023.07.14
[BOJ] 5427번 불 - python  (0) 2023.07.10