📌 문제
적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다.
크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은 색상이라 한다)
예를 들어, 그림이 아래와 같은 경우에
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
적록색약이 아닌 사람이 봤을 때 구역의 수는 총 4개이다. (빨강 2, 파랑 1, 초록 1) 하지만, 적록색약인 사람은 구역을 3개 볼 수 있다. (빨강-초록 2, 파랑 1)
그림이 입력으로 주어졌을 때, 적록색약인 사람이 봤을 때와 아닌 사람이 봤을 때 구역의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. (1 ≤ N ≤ 100)
둘째 줄부터 N개 줄에는 그림이 주어진다.
출력
적록색약이 아닌 사람이 봤을 때의 구역의 개수와 적록색약인 사람이 봤을 때의 구역의 수를 공백으로 구분해 출력한다.
예제 입력
5
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
예제 출력
4 3
📌 풀이
Code
import sys
from collections import deque
input = sys.stdin.readline
def BFS(start_r, start_c, color):
queue = deque() # 큐 생성
queue.append([start_r, start_c]) # 시작 좌표 enqueue
visited[start_r][start_c] = 1 # 시작 좌표 방문 표시
while queue:
r, c = queue.popleft()
for k in range(4): # 상하좌우 탐색
nr = r + dr[k]
nc = c + dc[k]
# 배열을 벗어나지 않고, 방문한적 없으며, 시작점과 같은 색깔이면 큐에 넣고 방문 표시
if 0 <= nr < N and 0 <= nc < N and not visited[nr][nc] and arr[nr][nc] in color:
queue.append([nr, nc])
visited[nr][nc] = 1
return
N = int(input()) # 그림 크기
arr = [list(input().strip()) for _ in range(N)] # 그림
# 델타
dr = [0, 0, 1, -1]
dc = [1, -1, 0, 0]
# 정상인
cnt = 0 # 본 구역의 개수
visited = [[0]*N for _ in range(N)] # 방문 리스트 초기화
for r in range(N):
for c in range(N):
if not visited[r][c]:
BFS(r, c, arr[r][c])
cnt += 1
print(cnt, end=' ')
# 색맹
cnt = 0 # 본 구역의 개수
visited = [[0]*N for _ in range(N)] # 방문 리스트 초기화
for r in range(N):
for c in range(N):
if not visited[r][c]:
if arr[r][c] == 'B': # 파란색이면
color = 'B' # 영역 탐색 대상은 파란색
else: # 파란색이 아니면
color = 'RG' # 영역 탐색 대상은 빨, 초
BFS(r, c, color)
cnt += 1
print(cnt)
Solution
1. 상하좌우를 탐색할 수 있는 델타 값 만들기
2. 정상인(색맹이 아닌 사람)이 본 구역의 개수를 세기 위해 카운트 변수, 방문 리스트 만들기
3. 0행 0열부터 N-1행 N-1열까지 반복문을 순회하여 BFS 탐색 시작점 설정
4. 시작점의 색깔과 같은 색깔인 인접 칸만 방문 표시하는 BFS 수행
5. BFS 함수가 한번 끝날 때마다 카운트 1 증가 (하나의 영역에 대해 방문 표시가 완료되었다는 뜻)
6. 위와 같은 방식으로 색맹이 본 구역의 개수도 세기
- 색맹의 경우, R과 G는 같은 영역으로 고려 (시작점이 R인 경우, BFS 수행 시 R, G 두 가지 색깔 인접 칸 모두에 대해 방문 표시)
깨달은 점
BFS를 쓰는 방법은 알았지만 어떤 경우에 써야할지 헷갈렸는데, 이번 문제를 통해 어느정도 감이 온 것 같아요!
그래프의 너비를 우선적으로 탐색하는 것이니,
2차원 배열에서는 가장 가까운 주변을 하나하나 탐색하며 가는 느낌이라고 보면 될 것 같네요.
주변을 일일이 다 보면서 사방으로 퍼져나가는 로직이 필요할 때, 앞으로 BFS를 바로 떠올려야겠습니다~

'Coding Test > Baekjoon' 카테고리의 다른 글
[백준] 10711 모래성(Python) - BFS (2) | 2024.08.28 |
---|---|
[백준] 12927 배수 스위치(Python) - Greedy (0) | 2024.08.26 |
[백준] 2669 직사각형 네개의 합집합의 면적 구하기(Python) - Simulation (0) | 2024.08.18 |
[백준] 2615 오목 (Python) - Brute Force (0) | 2024.08.18 |