TIL/Baekjoon

[10026] 적록색약

YOOZI. 2025. 3. 4. 14:53
728x90

문제

백준 문제

 

적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다.

크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은 색상이라 한다)

예를 들어, 그림이 아래와 같은 경우에

RRRBB
GGBBB
BBBRR
BBRRR
RRRRR

적록색약이 아닌 사람이 봤을 때 구역의 수는 총 4개이다. (빨강 2, 파랑 1, 초록 1) 하지만, 적록색약인 사람은 구역을 3개 볼 수 있다. (빨강-초록 2, 파랑 1)

그림이 입력으로 주어졌을 때, 적록색약인 사람이 봤을 때와 아닌 사람이 봤을 때 구역의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. (1 ≤ N ≤ 100)

둘째 줄부터 N개 줄에는 그림이 주어진다.

출력

적록색약이 아닌 사람이 봤을 때의 구역의 개수와 적록색약인 사람이 봤을 때의 구역의 수를 공백으로 구분해 출력한다.

예제 입력 1 

5
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR

예제 출력 1 

4 3

풀이

import sys
from collections import deque
input = sys.stdin.readline

# 방향 벡터 (상, 하, 좌, 우)
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]

def bfs(x, y, grid, visited, n):
    queue = deque([(x, y)])
    visited[x][y] = True
    color = grid[x][y]  # 시작점의 색상

    while queue:
        cx, cy = queue.popleft()

        for i in range(4):
            nx, ny = cx + dx[i], cy + dy[i]

            # 범위 확인 및 방문 여부와 색상 검사
            if 0 <= nx < n and 0 <= ny < n and not visited[nx][ny]:
                # 같은 색상인 경우만 탐색
                if grid[nx][ny] == color:
                    visited[nx][ny] = True
                    queue.append((nx, ny))

def count_regions(grid, n):
    visited = [[False] * n for _ in range(n)]
    regions = 0

    for i in range(n):
        for j in range(n):
            if not visited[i][j]:
                bfs(i, j, grid, visited, n)
                regions += 1

    return regions

# 입력 처리
n = int(input().strip())
normal_grid = [list(input().strip()) for _ in range(n)]

# 적록색약용 그리드 생성
blind_grid = [[('R' if color == 'G' else color) for color in row] for row in normal_grid]

# 정상인과 적록색약의 구역 수 계산
normal_count = count_regions(normal_grid, n)
blind_count = count_regions(blind_grid, n)

# 결과 출력
print(normal_count, blind_count)

각 구문 상세 해설

1. 방향 벡터 설정

dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
  • 상, 하, 좌, 우로 이동하기 위한 방향 벡터.
  • 각각 (위, 아래, 왼쪽, 오른쪽)을 의미함.

 

2. BFS 함수 정의

def bfs(x, y, grid, visited, n):
    queue = deque([(x, y)])
    visited[x][y] = True
    color = grid[x][y]  # 시작점의 색상
  • (x, y)를 시작점으로 하는 BFS 함수 정의.
  • 큐에 시작점을 넣고, 방문 처리.
  • color : 현재 위치의 색상을 저장.

 

3. BFS 탐색 과정

    while queue:
        cx, cy = queue.popleft()

        for i in range(4):
            nx, ny = cx + dx[i], cy + dy[i]

            # 범위 내에 있고, 방문하지 않았으며 같은 색상일 경우
            if 0 <= nx < n and 0 <= ny < n and not visited[nx][ny] and grid[nx][ny] == color:
                visited[nx][ny] = True
                queue.append((nx, ny))
  • 큐가 빌 때까지 반복:
    1. 현재 위치에서 상하좌우로 이동.
    2. 범위를 벗어나지 않고, 방문하지 않았으며, 같은 색상이면:
      • 방문 처리.
      • 큐에 새로운 위치 추가.

 

4. 영역 수 세기 함수

def count_regions(grid, n):
    visited = [[False] * n for _ in range(n)]
    regions = 0

    for i in range(n):
        for j in range(n):
            if not visited[i][j]:
                bfs(i, j, grid, visited, n)
                regions += 1

    return regions
  • visited : 방문 여부를 저장하는 2차원 리스트.
  • regions : 연결된 영역의 수를 카운트.
  • 모든 위치를 순회하며 방문하지 않은 위치에서 BFS를 수행하고 영역 수를 1 증가.

 

5. 입력 처리

n = int(input().strip())
normal_grid = [list(input().strip()) for _ in range(n)]
  • n : 그리드의 크기.
  • normal_grid : 입력받은 색깔 그리드 저장.

 

6. 적록색약용 그리드 생성

blind_grid = [['R' if color == 'G' else color for color in row] for row in normal_grid]
  • 적록색약은 **빨강(R)**과 **초록(G)**을 구분하지 못함.
  • 따라서 G를 R로 변환한 새로운 blind_grid 생성.

 

7. 정상인과 적록색약의 영역 수 계산

normal_count = count_regions(normal_grid, n)
blind_count = count_regions(blind_grid, n)
  • 정상인적록색약에 대해 각각 BFS 수행하여 영역 수 계산.
728x90

'TIL > Baekjoon' 카테고리의 다른 글

[4299] AFC 윔블던  (0) 2025.03.05
[3046] R2  (0) 2025.03.05
[14248] 점프 점프  (0) 2025.03.04
[2178] 미로 탐색  (0) 2025.03.04
[1260] DFS와 BFS  (0) 2025.03.04