BOJ 14502번 연구소 Python 문제 풀이
분류: Graph Traversal (그래프 탐색), dfs, bfs
https://www.acmicpc.net/problem/14502
from sys import stdin
from copy import deepcopy
from typing import List
lab, viruses = [], []
n, m, res = 0, 0, 0
dy = [1, -1, 0, 0]
dx = [0, 0, 1, -1]
def select_walls(start: int, cnt: int) -> None:
global res
# 벽 3개 모두 세우면 바이러스 확산 후 안전 지대 탐색
if cnt == 3:
lab_copy = deepcopy(lab)
for y, x in viruses:
dfs(y, x, lab_copy)
safezone = sum(i.count(0) for i in lab_copy)
res = max(safezone, res)
return
for i in range(start, n * m):
y, x = i // m, i % m
if lab[y][x] == 0:
lab[y][x] = 1
select_walls(i, cnt + 1)
lab[y][x] = 0
def dfs(y: int, x: int, lab_copy: List[List[int]]) -> None:
for i in range(4):
ny, nx = y + dy[i], x + dx[i]
if 0 <= ny < n and 0 <= nx < m and lab_copy[ny][nx] == 0:
lab_copy[ny][nx] = 2
dfs(ny, nx, lab_copy)
def cnt_safezone(lab_copy: List[List[int]]) -> int:
cnt = 0
for i in range(n):
for j in range(m):
if lab_copy[i][j] == 0:
cnt += 1
return cnt
def main():
def input():
return stdin.readline().rstrip()
global lab, viruses, n, m
n, m = map(int, input().split())
lab = [list(map(int, input().split())) for _ in range(n)]
# 바이러스 위치 저장
for i in range(n):
for j in range(m):
if lab[i][j] == 2:
viruses.append((i, j))
# 벽 세우기
select_walls(0, 0)
print(res)
if __name__ == "__main__":
main()
우선 select_walls()
에서 백트래킹으로 벽 3개를 빈 공간에 모두 세운다. 그리고 DFS를 이용하여 바이러스를 확산시키키고, 안전지대 개수를 구한다.
바이러스를 확산 시킬 때는lab
을 deepcopy하여 복사본에 바이러스를 확산시켜야 한다.
from sys import stdin
from typing import List
from itertools import combinations
from collections import deque
lab, viruses, blanks = [], [], []
n, m = 0, 0
dy = [1, -1, 0, 0]
dx = [0, 0, 1, -1]
def bfs(y: int, x: int, lab_copy: List[List[int]]) -> None:
dq = deque([(y, x)])
while dq:
cy, cx = dq.popleft()
for i in range(4):
ny, nx = cy + dy[i], cx + dx[i]
if 0 <= ny < n and 0 <= nx < m and lab_copy[ny][nx] == 0:
lab_copy[ny][nx] = 2
dq.append((ny, nx))
def main():
def input():
return stdin.readline().rstrip()
global lab, viruses, n, m
n, m = map(int, input().split())
lab = [list(map(int, input().split())) for _ in range(n)]
# 바이러스, 빈 공간 위치 저장
for i in range(n):
for j in range(m):
if lab[i][j] == 2:
viruses.append((i, j))
elif lab[i][j] == 0:
blanks.append((i, j))
res = 0
# 벽 세우기
combs = combinations(blanks, 3)
for comb in combs:
lab_copy = [row[:] for row in lab]
for y, x in comb:
lab_copy[y][x] = 1
# 벽 3개 다 세우면 바이러스 확산
for y, x in viruses:
bfs(y, x, lab_copy)
# 안전 지대 개수 구하기
safezone = sum(i.count(0) for i in lab_copy)
res = max(safezone, res)
print(res)
if __name__ == "__main__":
main()
이전 풀이와 달리 itertools의 combinations
를 이용하여 벽 위치를 선택하였다. 그리고 벽을 세우고 바이러스를 확산시킬 때 BFS 탐색을 이용하였다. 또한 lab
을 deepcopy할 때, deepcopy()
메서드를 사용하지 않고 아래 방법을 사용했다.
lab_copy = [row[:] for row in lab]
그리고 안전 지대 개수 세는 방식을 아래와 같이 한 줄로 바꾸었다.
safezone = sum(i.count(0) for i in lab_copy)
채점 결과 수행속도가 이전 코드보다 빨랐다.