[Node.js | JavaScript] 백준 10026 적록색약 코드
@corinthioniaFebruary 6, 2024
문제
적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다.
크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은 색상이라 한다)
예를 들어, 그림이 아래와 같은 경우에
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
적록색약이 아닌 사람이 봤을 때 구역의 수는 총 4개이다. (빨강 2, 파랑 1, 초록 1) 하지만, 적록색약인 사람은 구역을 3개 볼 수 있다. (빨강-초록 2, 파랑 1)
그림이 입력으로 주어졌을 때, 적록색약인 사람이 봤을 때와 아닌 사람이 봤을 때 구역의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. (1 ≤ N ≤ 100)
둘째 줄부터 N개 줄에는 그림이 주어진다.
출력
적록색약이 아닌 사람이 봤을 때의 구역의 개수와 적록색약인 사람이 봤을 때의 구역의 수를 공백으로 구분해 출력한다.
Solution
- 처음에는 적록색약인 사람과 아닌 사람에 대해 각각 BFS 함수를 따로 작성했는데, 두 번째에는 하나의 BFS 함수만 사용하도록 구현
- 적록색약이 아닌 경우부터 BFS를 이용하여 구역의 개수를 센 뒤, 그래프의 'G'를 모두 'R'로 변환하는 작업 수행
코드 1 - BFS 함수를 각각 작성할 경우
const path = process.platform === 'linux' ? '/dev/stdin' : 'input.txt';
const input = require('fs').readFileSync(path).toString().trim().split('\n');
const N = Number(input.shift());
const graph_a = input.map(inp => inp.split(''));
const graph_b = input.map(inp => inp.split(''));
const dx = [-1, 1, 0, 0];
const dy = [0, 0, -1, 1];
let cnt_a = 0; // 적록색약인 아닌 경우
let cnt_b = 0; // 적록색약이 경우
// 적록색약이 아닌 경우에 대해 계산
const BFS_A = (a, b) => {
const color = graph_a[a][b];
let q = [];
q.push([a, b]);
while (q.length) {
const [x, y] = q.shift();
graph_a[x][y] = ''; // 방문처리
for (let i = 0; i < 4; i++) {
const nx = x + dx[i];
const ny = y + dy[i];
if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;
if (graph_a[nx][ny] === color) {
graph_a[nx][ny] = '';
q.push([nx, ny]);
}
}
}
};
// 적록색약인 경우에 대해 계산
const BFS_B = (a, b) => {
const color = graph_b[a][b] === 'G' ? 'R' : graph_b[a][b];
let q = [];
q.push([a, b]);
while (q.length) {
const [x, y] = q.shift();
graph_b[x][y] = ''; // 방문처리
for (let i = 0; i < 4; i++) {
const nx = x + dx[i];
const ny = y + dy[i];
if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;
if (color === 'R' && graph_b[nx][ny] === 'G') {
graph_b[nx][ny] = '';
q.push([nx, ny]);
continue;
}
if (graph_b[nx][ny] === color) {
graph_b[nx][ny] = '';
q.push([nx, ny]);
}
}
}
};
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (graph_a[i][j]) {
BFS_A(i, j);
cnt_a++;
}
}
}
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (graph_b[i][j]) {
BFS_B(i, j);
cnt_b++;
}
}
}
console.log(cnt_a, cnt_b);
코드 2 - 하나의 BFS 함수를 사용할 경우
const path = process.platform === 'linux' ? '/dev/stdin' : 'input.txt';
const input = require('fs').readFileSync(path).toString().trim().split('\n');
const N = Number(input.shift());
let graph = input.map(inp => inp.split(''));
let visited_a = new Array(N).fill(0).map(() => new Array(N).fill(0));
let visited_b = new Array(N).fill(0).map(() => new Array(N).fill(0));
const dx = [-1, 1, 0, 0];
const dy = [0, 0, -1, 1];
const BFS = (a, b, visited) => {
visited[a][b] = 1;
let q = [];
q.push([a, b]);
while (q.length) {
const [x, y] = q.shift();
visited[x][y] = 1;
for (let i = 0; i < 4; i++) {
const nx = x + dx[i];
const ny = y + dy[i];
if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;
if (visited[nx][ny] === 0 && graph[x][y] === graph[nx][ny]) {
visited[nx][ny] = 1;
q.push([nx, ny]);
}
}
}
};
let a = 0; // 적록색약이 아닌 경우
let b = 0; // 적록색약인 경우
// 적록색약이 아닌 경우
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (visited_a[i][j] === 0) {
BFS(i, j, visited_a);
a++;
}
}
}
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (graph[i][j] === 'G') {
graph[i][j] = 'R';
}
}
}
// 적록색약인 경우
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (visited_b[i][j] === 0) {
BFS(i, j, visited_b);
b++;
}
}
}
console.log(a, b);
← 이전 글[Node.js | JavaScript] 백준 1697 숨바꼭질 코드
다음 글 →[Node.js | JavaScript] 백준 2805 나무 자르기 코드