크기의 그리드에 R(빨강), G(초록), B(파랑) 중 하나의 색칠이 되어 있습니다. 상하좌우로 인접해 있는 같은 색상은 하나의 구역으로 봅니다. 단, 적록색약인 사람은 빨간색과 초록색의 차이를 거의 느끼지 못하므로 같은 구역으로 봅니다.
이때, 적록색약이 아닌 사람이 봤을 때의 구역의 수와 적록색약인 사람이 봤을 때의 구역의 수를 공백으로 구분해 출력하는 문제입니다.
이 문제는 하나의 맵을 두고 두 번의 BFS 탐색을 진행해야 합니다.
일반적인 시각과 적록색약의 시각을 나누어 처리해야 하는데, 가장 효율적인 방법은 '적록색약 전용 탐색 함수'를 따로 만들지 않고 데이터를 조작하는 것입니다.
graph[nx][ny] == graph[x][y] 조건을 통해 같은 알파벳을 가진 칸끼리만 연결 요소를 구성하여 count_normal을 구합니다.for문을 돌며 맵 전체의 R을 G로 (혹은 G를 R로) 모두 덮어씌웁니다. 이렇게 하면 적록색약의 시야가 배열 데이터로 완벽히 구현됩니다.True가 되어버린 visited 배열을 다시 사이즈에 맞게 False로 싹 비워줍니다.bfs() 함수를 수정 없이 그대로 다시 호출하여 count_impaired를 구합니다.import sys
from collections import deque
input = sys.stdin.readline
N = int(input())
graph = [list(input().strip()) for _ in range(N)]
visited = [[False] * N for _ in range(N)]
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
def bfs(start_x, start_y):
queue = deque([(start_x, start_y)])
visited[start_x][start_y] = True
while queue:
x, y = queue.popleft()
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx < N and 0 <= ny < N and not visited[nx][ny] and graph[nx][ny] == graph[x][y]:
queue.append((nx, ny))
visited[nx][ny] = True
count_normal = 0
for i in range(N):
for j in range(N):
if not visited[i][j]:
bfs(i, j)
count_normal += 1
# 적록색약 시뮬레이션을 위해 'R'을 모두 'G'로 변환
for i in range(N):
for j in range(N):
if graph[i][j] == 'R':
graph[i][j] = 'G'
# 방문 기록 초기화
visited = [[False] * N for _ in range(N)]
count_impaired = 0
for i in range(N):
for j in range(N):
if not visited[i][j]:
bfs(i, j)
count_impaired += 1
print(count_normal, count_impaired)
if (정상일 때) ~ elif (색약일 때 R과 G를 같게 처리) ~ 이런 식으로 조건을 덕지덕지 붙이는 것을 고려했습니다. 하지만 데이터 자체를 색약의 눈에 맞게 변환시켜버리면, 탐색 로직(graph[nx][ny] == graph[x][y]) 자체는 전혀 건드릴 필요가 없어 코드의 중복을 막고 유지보수성을 크게 높일 수 있다는 아주 중요한 설계 팁을 배웠습니다.visited) 초기화의 중요성: 두 번째 탐색을 시작하기 전에 visited 배열을 초기화하지 않으면 이미 방문한 것으로 인식되어 두 번째 값이 0이 나와버립니다. 다중 탐색을 진행할 때는 반드시 이전 탐색의 흔적을 리셋해 주어야 한다는 기본 원칙을 다시 한번 상기했습니다.