[백준/파이썬] 14502번 연구소 풀이

업데이트:



문제 정보


풀이

문제

연구소 지도에서 빈 칸(0) 중 3곳에 벽을 세운 뒤, 바이러스(2)가 퍼진 결과를 시뮬레이션했을 때 안전 영역(끝까지 0으로 남는 칸)의 최댓값을 구하는 문제입니다.

코드

import sys; read=sys.stdin.readline
from collections import deque

n, m = map(int, read().split())
cells = [list(map(int, read().split())) for _ in range(n)]

emptyCells, virusCells = [], []
for i in range(n):
    for j in range(m):
        if cells[i][j] == 0: emptyCells.append((i,j))
        elif cells[i][j] == 2: virusCells.append((i,j))

wallCases = []

def backTracking(wallCase):
    if len(wallCase) >= 3:
        wallCases.append(wallCase)
        return
    for i in range(wallCase[-1]+1, len(emptyCells)+len(wallCase)-2):
        backTracking(wallCase+[i])

for i in range(len(emptyCells)-2):
    backTracking([i])

virusCellMin = 64
directions = [(-1, 0),(0, 1),(1, 0),(0, -1)]

q = deque([])
enQ = q.append
deQ = q.popleft

for wallCase in wallCases:
    q.clear()
    tmpCells = [cells[i][:] for i in range(n)]
    for virusCell in virusCells: enQ(virusCell)
    for idx in wallCase:
        tmpCells[emptyCells[idx][0]][emptyCells[idx][1]] = 1
    tmpVirusCnt = len(virusCells)

    while q:
        virus = deQ()
        for direction in directions:
            i, j = virus[0] + direction[0], virus[1] + direction[1]
            if 0 <= i < n and\
               0 <= j < m and\
               tmpCells[i][j] == 0:
                tmpCells[i][j] = 2
                enQ((i, j))
                tmpVirusCnt += 1
                if tmpVirusCnt >= virusCellMin:
                    q.clear()
                    break
                
    virusCellMin = min(tmpVirusCnt, virusCellMin)

print(len(emptyCells) - 3 - virusCellMin + len(virusCells))

설명

전형적인 조합 + BFS 시뮬레이션 문제입니다.

  • 빈 칸 중 3개를 고르는 모든 경우를 백트래킹으로 생성합니다.
  • 각 경우마다 임시 맵을 복사하고 바이러스 확산을 BFS로 계산합니다.
  • 감염 수가 이미 현재 최솟값 이상이면 조기 중단해 시간을 줄입니다.
  • 최종적으로 안전 영역 최대값을 출력합니다.


댓글남기기