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))
- 큐가 빌 때까지 반복:
- 현재 위치에서 상하좌우로 이동.
- 범위를 벗어나지 않고, 방문하지 않았으며, 같은 색상이면:
- 방문 처리.
- 큐에 새로운 위치 추가.
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 |