블로그 이름 뭐로 하지

[알고리즘/파이썬] 백준 2638 - 치즈 본문

알고리즘

[알고리즘/파이썬] 백준 2638 - 치즈

발등이 따뜻한 사람 2024. 1. 16. 22:18

문제

https://www.acmicpc.net/problem/2638

 

2638번: 치즈

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

www.acmicpc.net

 

풀이

1. 모서리는 치즈가 없다고 했으니 (0,0)부터 근접한 모든 공기 부분을 BFS로 탐색하여 -1로 변경해준다. (그러면 치즈 내면의 공기 부분은 0으로 남아있을 것) 

2. 2차 for문을 돌면서 arr[i][j] == 1(치즈)일 경우에 근접한 4면 중 공기가 2면 이상인지 확인한다. 두 면 이상이 공기라면 q에 해당 좌표를 넣어둔다.

3. q가 빌 때까지 해당 치즈들을 모두 -1(공기)로 바꿔준다.

 

처음에 이렇게만 했다가 시간초과가 나서 뭘까 어느 부분이 비효율적인거지... 했는데 그냥 중간에 while문을 계속 돌아서 무한루프에 빠져서 그런거였다. 

내가 간과했던 점은 치즈가 공기가 되면서 내면에 있던 0 공기가 -1의 겉 공기가 될 수 있었던건데 그걸 중간에 체크해주지 않았기 때문에 생긴 문제였다. 그래서 while문을 돌면서 1번 과정을 각 단계마다 계속해서 수행할 수 있게끔 변경해주었다!

 

 

코드

from collections import deque
n,m = map(int,input().split())
arr = []
for _ in range(n):
    tmp = list(map(int,input().split()))
    arr.append(tmp)


dx = [1,-1,0,0]
dy = [0,0,1,-1]

def find_air():
    visited = [[0 for _ in range(m)] for _ in range(n)]
    q = deque()
    q.append((0,0))

    while q:
        x,y = q.popleft()

        for i in range(4):
            nx = x+ dx[i]
            ny = y+ dy[i]

            if nx<0 or ny<0 or nx>=n or ny>=m:
                continue
            if (arr[nx][ny] == 0 or arr[nx][ny] == -1) and visited[nx][ny] == 0:
                arr[nx][ny] = -1
                visited[nx][ny] = 1
                q.append((nx,ny))


def check_melt_spot(x,y):
    air_count = 0
    for i in range(4):
        nx = x+ dx[i]
        ny = y+ dy[i]

        if nx<0 or ny<0 or nx>=n or ny>=m:
            continue
        if arr[nx][ny] == -1:
            air_count += 1

    if air_count >= 2:
        return True
    else:
        return False

time = 0 
while True:
    find_air()
    
    flag = 0
    change_q = deque()



    for i in range(n):
        for j in range(m):
            if arr[i][j] == 1:
                flag = 1
                if check_melt_spot(i,j):
                    change_q.append((i,j))

    
    while change_q:
        x,y = change_q.popleft()
        arr[x][y] = -1
    
    if flag == 0:
        break

    time += 1

print(time)