알고리즘/백준

BOJ | 2638 - 치즈 (python)

유하 yuha 2022. 2. 24. 00:38

🧀 백준 2638번 치즈

 

 

 


✏️ 문제

N×M의 모눈종이 위에 아주 얇은 치즈가 <그림 1>과 같이 표시되어 있다. 단, N 은 세로 격자의 수이고, M 은 가로 격자의 수이다. 이 치즈는 냉동 보관을 해야만 하는데 실내온도에 내어놓으면 공기와 접촉하여 천천히 녹는다. 그런데 이러한 모눈종이 모양의 치즈에서 각 치즈 격자(작 은 정사각형 모양)의 4변 중에서 적어도 2변 이상이 실내온도의 공기와 접촉한 것은 정확히 한시간만에 녹아 없어져 버린다. 따라서 아래 <그림 1> 모양과 같은 치즈(회색으로 표시된 부분)라면 C로 표시된 모든 치즈 격자는 한 시간 후에 사라진다.

<그림 1>

<그림 2>와 같이 치즈 내부에 있는 공간은 치즈 외부 공기와 접촉하지 않는 것으로 가정한다. 그러므 로 이 공간에 접촉한 치즈 격자는 녹지 않고 C로 표시된 치즈 격자만 사라진다. 그러나 한 시간 후, 이 공간으로 외부공기가 유입되면 <그림 3>에서와 같이 C로 표시된 치즈 격자들이 사라지게 된다.

<그림 2>

<그림 3>

모눈종이의 맨 가장자리에는 치즈가 놓이지 않는 것으로 가정한다. 입력으로 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로 표시된다. 또한, 각 0과 1은 하나의 공백으로 분리되어 있다.

 

출력

출력으로는 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 정수로 첫 줄에 출력한다.

 

 


💡 해결방법

도움을 주신 @짱친 정말정말 감사합니다

 

아래와 같은 단계를 visited(아래 설명)가 모두 0이 될때까지 반복한다.

1. bfs로 치즈 안쪽(영향을 받지 않는)의 0을 1로 바꿔준다.
2. 2변 이상이 공기와 맞닿는 부분을 0으로 바꾸고 result를 1씩 증가한다.

 

 

bfs를 통해 치즈 안쪽의 0 을 모두 1로 바꿔주어야 한다.

0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 1 1 0
0 1 0 1 1 1 0 1 0
0 1 0 0 1 0 0 1 0
0 1 0 1 1 1 0 1 0
0 1 1 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0

 

위와 같은 입력에서 안쪽에 있는 0부분을 1로 먼저 채워주어야 한다.

 

0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 1 1 0
0 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 0
0 1 1 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0

 

안쪽에 있는 치즈는 영향을 받지 않으므로 위와 같이 안쪽을 1로 채워주어야 한다.

 

모두 1로 채워준 새로운 치즈 리스트를 하나 더 만든 다음(코드 상에선 visited)

만약 cheese가 0이면 visited를 0으로 바꿔주는 bfs를 수행하면 위와 같은 결과를 얻을 수 있다.

 

2변 이상 맞닿는 부분은 상하좌우를 확인하며 만약 2변 이상 공기와 맞닿을 경우 cheese 리스트에서 0으로 바꿔준다.

이후 한번씩 공기와 맞닿는 부분을 모두 0으로 바꾸어 줄 때마다 result를 1씩 증가한다.

 

Q. 왜 visited로 확인하고 cheese를 0으로 수정하는지?

A. 안쪽 배열에 모두 차 있는 visited로 확인하고 cheese로 수정을 해야 만약 cheese가 0으로 바뀔 경우 첫번째 돌아갈 때 공기와 맞닿는 변의 개수를 정확하게 알 수 있다. visited가 변경될 경우 2변 이상 맞닿지 않는 부분도 맞닿게 된다고 판단될 수 있다.

 

 

👩🏻‍💻 소스코드

# 2638 : 치즈

import sys
from collections import deque
input = sys.stdin.readline

N, M = map(int, input().split())
cheese = [list(map(int, input().split())) for _ in range(N)]
d = [(1, 0), (0, 1), (-1, 0), (0, -1)]
result = 0


def bfs(x, y):
    visited = [[1 for _ in range(M)] for _ in range(N)]
    q = deque()
    q.append((x, y))

    while q:
        x, y = q.popleft()
        for i in range(4):
            nx = x+d[i][0]
            ny = y+d[i][1]

            if 0 <= nx < N and 0 <= ny < M:
                if cheese[nx][ny] == 0 and visited[nx][ny] == 1:
                    visited[nx][ny] = 0
                    q.append((nx, ny))
    return visited


while sum(map(sum, cheese)) != 0:

    visited = bfs(0, 0)

    for i in range(N):
        for j in range(M):
            cnt = 0
            if visited[i][j] == 1:
                for k in range(4):
                    nx = i+d[k][0]
                    ny = j+d[k][1]
                    if 0 <= nx < N and 0 <= ny < M and visited[nx][ny] == 0:
                        cnt += 1
            if cnt >= 2:
                cheese[i][j] = 0
    result += 1

print(result)

 


 

 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로

www.acmicpc.net