728x90
문제
적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다.크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은 색상이라 한다)예를 들어, 그림이 아래와 같은 경우에
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
적록색약이 아닌 사람이 봤을 때 구역의 수는 총 4개이다. (빨강 2, 파랑 1, 초록 1) 하지만, 적록색약인 사람은 구역을 3개 볼 수 있다. (빨강-초록 2, 파랑 1)그림이 입력으로 주어졌을 때, 적록색약인 사람이 봤을 때와 아닌 사람이 봤을 때 구역의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. (1 ≤ N ≤ 100)
둘째 줄부터 N개 줄에는 그림이 주어진다.
출력
적록색약이 아닌 사람이 봤을 때의 구역의 개수와 적록색약인 사람이 봤을 때의 구역의 수를 공백으로 구분해 출력한다.
연결요소의 개수를 찾는 문제이다. 특별한 점이라 하면 일반인/적록색맹 대상으로 두번의 탐색을 수행해야 한다는 점이다.
int N;
cin >> N;
vector<vector<char>> paint(N, vector<char>(N));
vector<vector<char>> paint_blind(N, vector<char>(N));
vector<vector<bool>> visited(N, vector<bool>(N, false));
for (int i = 0; i < N; i++)
{
string input;
cin >> input;
for (int j = 0; j < N; j++)
{
paint[i][j] = input[j];
if (input[j] != 'B')
paint_blind[i][j] = 'X';
else
paint_blind[i][j] = input[j];
}
}
위와 같이 RGB를 입력받되, B가 아니면 paint_blind에는 X로 저장한다.
int dr[4] = {1, -1, 0, 0};
int dc[4] = {0, 0, 1, -1};
void bfs(vector<vector<char>> &g, int i, int j, vector<vector<bool>> &visited)
{
int g_size = g.size();
queue<pair<int, int>> q;
q.push({i, j});
visited[i][j] = true;
while (!q.empty())
{
auto [r, c] = q.front();
q.pop();
for (int d = 0; d < 4; d++)
{
int nr = r + dr[d];
int nc = c + dc[d];
if ((nr < 0 || nr >= g_size) || (nc < 0 || nc >= g_size))
continue;
if (visited[nr][nc] || g[nr][nc] != g[r][c])
continue;
q.push({nr, nc});
visited[nr][nc] = true;
}
}
}
bfs 함수는 단순히 탐색을 수행한다.
int division = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (!visited[i][j])
{
bfs(paint, i, j, visited);
division++;
}
cout << division << " ";
division = 0;
visited.assign(N, vector<bool>(N, false));
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (!visited[i][j])
{
bfs(paint_blind, i, j, visited);
division++;
}
cout << division;
입력을 받은 후에 paint와 paint_blind의 각 좌표에 대해 bfs 탐색을 수행한다. paint에 대해 수행한 이후에는 반드시 division과 visited를 초기화해주어야 한다.
전체 코드
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int dr[4] = {1, -1, 0, 0};
int dc[4] = {0, 0, 1, -1};
void bfs(vector<vector<char>> &g, int i, int j, vector<vector<bool>> &visited)
{
int g_size = g.size();
queue<pair<int, int>> q;
q.push({i, j});
visited[i][j] = true;
while (!q.empty())
{
auto [r, c] = q.front();
q.pop();
for (int d = 0; d < 4; d++)
{
int nr = r + dr[d];
int nc = c + dc[d];
if ((nr < 0 || nr >= g_size) || (nc < 0 || nc >= g_size))
continue;
if (visited[nr][nc] || g[nr][nc] != g[r][c])
continue;
q.push({nr, nc});
visited[nr][nc] = true;
}
}
}
int main()
{
// freopen("input.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
vector<vector<char>> paint(N, vector<char>(N));
vector<vector<char>> paint_blind(N, vector<char>(N));
vector<vector<bool>> visited(N, vector<bool>(N, false));
for (int i = 0; i < N; i++)
{
string input;
cin >> input;
for (int j = 0; j < N; j++)
{
paint[i][j] = input[j];
if (input[j] != 'B')
paint_blind[i][j] = 'X';
else
paint_blind[i][j] = input[j];
}
}
int division = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (!visited[i][j])
{
bfs(paint, i, j, visited);
division++;
}
cout << division << " ";
division = 0;
visited.assign(N, vector<bool>(N, false));
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (!visited[i][j])
{
bfs(paint_blind, i, j, visited);
division++;
}
cout << division;
}
728x90
'Baekjoon' 카테고리의 다른 글
[Baekjoon] 7569: 토마토 - (C3, G5) BFS (0) | 2025.01.30 |
---|---|
[Baekjoon] 5430: AC - (C3, G5) Deque, String (0) | 2025.01.29 |
[Baekjoon] 1931: 회의실 배정 - (C3, G5) Sorting, Greedy Method (0) | 2025.01.28 |
[Baekjoon] 1074: Z - (C3, G5) Divide&Conquer, Recursion (0) | 2025.01.27 |
[Baekjoon] 11403: 경로 찾기 - (C3, S1) BFS (0) | 2025.01.26 |