[백준_Python] 7576번 - 토마토 [골드 5]

황준성·2024년 12월 11일
0

BOJ_Python

목록 보기
36/70
post-thumbnail

문제

입력

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 상자에 담긴 토마토의 정보가 주어진다. 하나의 줄에는 상자 가로줄에 들어있는 토마토의 상태가 M개의 정수로 주어진다. 정수 1은 익은 토마토, 정수 0은 익지 않은 토마토, 정수 -1은 토마토가 들어있지 않은 칸을 나타낸다.

토마토가 하나 이상 있는 경우만 입력으로 주어진다.

출력

여러분은 토마토가 모두 익을 때까지의 최소 날짜를 출력해야 한다. 만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.

입력 예시 1

6 4
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1

출력 예시 1

8

문제 이해

이 문제는 처음으로 푸는 골드 난이도였다. 엄청 어려워보이거나 하지는 않았다. DFS/BFS 기준으로는 실버 1까지는 많이 풀어봤기 때문이라고 생각한다. 하지만 어떻게 풀어야할지 명확하게 생각해내지는 못했다. 원래는 visited를 임시로 따로 만들어서 그걸보면서 원본을 수정하려고 했는데 그렇게는 풀수가 없는 것 같다. 그래서 다른 사람의 풀이를 참고했다.

참고한 블로그
https://jae04099.tistory.com/entry/%EB%B0%B1%EC%A4%80-7576-%ED%86%A0%EB%A7%88%ED%86%A0-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%95%B4%EC%84%A4%ED%8F%AC%ED%95%A8

지금까지 문제를 풀면서 모르는 문제는 다른 사람의 풀이를 꽤 봐왔다. 그런데 위 블로그처럼 이해가 잘되고 구체적으로 풀이를 한 사람은 처음 봤다. 주석으로 설명을 엄청 자세하게 한 코드와 그걸 모두 지운 코드를 둘다 게시했는데 주석으로 설명을 정말 잘했다. 정말 배워야 할 부분이라고 생각한다. 저 사람은 좋은 곳에 취업했을지 모르겠다. 나도 열심히 공부해서 나중에 졸업하고 좋은 곳에 취직하고 싶다.

여담은 여기까지하고 문제 풀이에 대해서 설명한다. 이 문제를 풀려면 처음 익은 토마토의 위치를 기억하고 BFS를 계속 돌리면서 상하좌우에 있는 값은 리스트에 있는 값에 1을 더한 값을 넣어준다. 즉, 처음에 익힌 토마토의 위치가 1로 주어지니까 1을 기준으로 상하좌우를 살펴보고 0인 곳은 2의 값을 넣어주고, 2를 기준으로 상하좌우로 0인 값에는 3을 넣어주는 방식이다. 물론 큐에 좌표값을 넣으면서.

그런 방식으로 하면, 2차원 리스트에서 가장 큰 값에서 1을 뺀 값이 총 반복된 횟수가 된다. 모든 토마토가 익을 수 없는 상황을 판단하려면 BFS를 호출한 후에 원본 연결 값에 0이 있으면 -1을 출력하고 프로그램을 종료하면 된다.

코드

# 백준 7576번 토마토

# 입력 효율화
import sys
input = sys.stdin.readline
# deque가 시간복잡도 측면에서 훨씬 효율적이라고 한다
from collections import deque

# 방향벡터 동-서-남-북순
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]

# function BFS
def BFS():
    global queue, box

    while queue:

        y, x = queue.popleft()

        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0 <= nx < M and 0 <= ny < N and box[ny][nx] == 0:
                box[ny][nx] = box[y][x] + 1 # 하루가 지날때마다 값을 1씩증가해서 넣는다
                queue.append((ny, nx))
                # 퍼져나갈 때마다 값을 증가시켜 주는 방식
                # 처음 익은 토마토는 1, 그 다음에 익으면 2, 3..4..

# 0. 입력 및 초기화
M, N = map(int, input().split()) #M가로 N세로
box = [] # 토마토 박스 리스트

queue = deque() # BFS호출 전에 큐에 값을 넣어줘야 해서 미리 선언

# 1. 연결정보 입력
for _ in range(N):
    box.append(list(map(int, input().split())))

# 2. 처음 사과 위치 큐에 기억 및 BFS호출
# 입력으로 들어왔을때의 익은 토마토의 위치를 저장
for i in range(N):
    for j in range(M):
        if box[i][j] == 1:
            queue.append((i, j))
            # 이 값을 기준으로 퍼져나갈 거임

BFS()

# 3. 출력
for i in range(N):
    for j in range(M):
        if box[i][j] == 0: # 값이 0인게 하나라도 있으면 상하좌우로는 익힐 수가 없음
            print(-1)
            sys.exit(0) # 정상적인 프로그램 종료

# 모두 익었다면 가장 큰 값을 출력 -> 한번 나아갈때마다 1씩 증가해서 값을 넣어줬다
# 그래서 가장 큰 값에서 1을 빼면 그게 횟수가 된다
max_value = max(map(max, box))
print(max_value - 1)
profile
Make progress

0개의 댓글