문제
요약
N*M 행렬로 표현되는 맵에서 0은 이동할 수 있는 곳을, 1은 이동할 수 없는 벽을 나타낸다. 각각의 벽에 대해서 다음을 구해보자.
- 벽을 부수고 이동할 수 있는 곳으로 변경한다.
- 그 위치에서 이동할 수 있는 칸의 개수를 세어본다.
분류
- BFS
- DFS
풀이
1. 내 풀이 (BFS)
나는 0을 기준으로 생각했다. 1을 기준으로 생각하려면, 0의 면적을 미리 계산해 전처리를 하지 않으면 같은 공간을 여러 번 탐색해야 하기에 시간 초과가 나왔다.
각 0을 중심으로 인접한 곳을 탐색한다. 벽을 만나면 좌표를 세트에 튜플 형태로 저장해 두었다가 인접한 0의 면적만큼 더해주었다. 하나의 벽에 여러 개의 0들이 인접할 수 있기 때문에 중복을 처리하기 위해 세트를 사용했다.
시간 복잡도는 O(NM)이다. (O(N^2))
import sys
from collections import deque
input = sys.stdin.readline
n, m = map(int, input().split())
arr = [list(map(int, list(input().rstrip()))) for _ in range(n)]
ans = [a.copy() for a in arr]
dx, dy = [0, 1, 0, -1], [1, 0, -1, 0]
visit = [[False] * m for _ in range(n)]
for zero_r in range(n):
for zero_c in range(m):
if arr[zero_r][zero_c] == 0 and not visit[zero_r][zero_c]:
s = set()
queue = deque([(zero_r, zero_c)])
cnt = 0
one_list = []
while queue:
r, c = queue.popleft()
if visit[r][c]:
continue
visit[r][c] = True
cnt += 1
for i in range(4):
nr, nc = r + dy[i], c + dx[i]
if 0 <= nr < n and 0 <= nc < m and not visit[nr][nc] and arr[nr][nc] == 0:
queue.append((nr, nc))
elif 0 <= nr < n and 0 <= nc < m and arr[nr][nc] == 1:
one_list.append((nr, nc))
for y, x in one_list:
if (y, x) not in s:
ans[y][x] = (ans[y][x] + cnt) % 10
s.add((y, x))
for a in ans:
for b in a:
print(b, end="")
print()
2. DFS
- BFS에서의 큐를 스택으로만 바꿔주면 된다.