
코딩 테스트 양식
출처
인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다.
연구소는 크기가 N×M인 직사각형으로 나타낼 수 있으며, 직사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다.
일부 칸은 바이러스가 존재하며, 이 바이러스는 상하좌우로 인접한 빈 칸으로 모두 퍼져나갈 수 있다. 새로 세울 수 있는 벽의 개수는 3개이며, 꼭 3개를 세워야 한다.입력 7 7 2 0 0 0 1 1 0 0 0 1 0 1 2 0 0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0출력 27
문제의 조건 다음과 같다.
1. 바이러스는 상하좌우로 퍼진다.
2. 바이러스는 벽을 뚫지 못한다.
3. 벽을 추가로 세 개를 세워 최대 안전구역을 확보하라.
최대 안전구역을 구해야하는데 그렇다면 조건을 참고하여 다시 절차적으로 바꿔보자.
1. 벽을 세 개를 세운다.(중복되지 않는 조합을 구하여라.)
2. 바이러스를 퍼뜨린다.(BFS를 통해 바이러스를 퍼뜨려라.)
3. 안전영역의 수를 카운트한다.(0의 개수를 카운트한다.)
from itertools import combinations
from collections import deque
from copy import deepcopy
import sys
input = sys.stdin.readline
# 0은 빈 칸, 1은 벽 2는 바이러스
# 연구소의 지도가 주어졌을 경우
# 벽을 세 개 세운 후 가장 큰 안전영역을 구하여라
n, m = map(int, input().split())
map = [list(map(int, input().split())) for _ in range(n)]
# 특정 0을 세 개를 중복되지 않게 뽑아야 한다. 몇 가지 경우의 수가 나오며,
zero_area = []
virus = deque()
for i in range(n):
for j in range(m):
if map[i][j] == 0:
zero_area.append((i,j))
if map[i][j] == 2:
virus.append((i,j))
make_wall = list(combinations(zero_area,3))
# 바이러스를 퍼뜨려야한다.
max_safety = 0
for walls in make_wall:
# 벽을 뽑고 벽을 세워야함.
temp_map = deepcopy(map)
for wall in walls:
temp_map[wall[0]][wall[1]] = 1 # 추가 벽 세우기
# 새로 벽을 세웠으니 바이러스를 퍼뜨려야함. bfs
moves = [(0,1),(1,0),(-1,0),(0,-1)]
temp_virus = deepcopy(virus)
while temp_virus:
x,y = temp_virus.popleft()
for dx, dy in moves:
nx, ny = x+dx, y+dy
if 0<=nx<n and 0<=ny<m and temp_map[nx][ny]==0:
temp_map[nx][ny] = 2
temp_virus.append((nx,ny))
cnt = 0
# 청정지역을 찾아야함.
for i in range(n):
for j in range(m):
if temp_map[i][j] == 0:
cnt +=1
# 최대 안전구역 크기를 구해야함.
max_safety = max(max_safety, cnt)
print(max_safety)
기분 좋게 문제를 풀었다. 3가지 할 일을 세우는 것이 가장 중요한 문제이다.
알고리즘을 모른다면 풀기 힘든 문제이다.
combination을 사용하지 안았다면 또한 3중 for문을 사용해서 조합을 구했을 듯 싶다..
음 메모리를 좀 많이 사용한 듯 하다. 메모리 제한이 좀 더 타이트했다면 추가 벽 세운 것을 다시 원상복구 하는 식으로 코드를 변경했을 듯 하다.
앞으로 이렇게 계획적으로 문제 푸는 연습을 해야겠다.