본문 바로가기
Beakjoon&프로그래머스/Java

[백준/Java] 10026번 적록색약

by 현장 2026. 1. 18.

-Code

import java.io.*;
import java.util.ArrayDeque;
import java.util.Deque;

public class BOJ10026 {
    static class PosInfo {
        int row, col;

        public PosInfo (int row, int col) {
            this.row = row;
            this.col = col;
        }
    }
    static boolean[][] visited;

    public static void main(String[] args) throws IOException {
        BufferedReader br =
                new BufferedReader(new InputStreamReader(System.in));

        int size = Integer.parseInt(br.readLine());

        char[][] art = new char[size][size];
        for (int i = 0; i < size; i++) {
            String row = br.readLine();
            for (int j = 0; j < size; j++) {
                art[i][j] = row.charAt(j);
            }
        }
        // answer 변수 선언
        int answer1 = 0;
        int answer2 = 0;
        // 일반인 visited 셋팅
        visited = new boolean[size][size];
        // 일반인 그림 탐색 (BFS)
        for (int row = 0; row < size; row++) {
            for (int col = 0; col < size; col++) {
                if (!visited[row][col]) {
                    PosInfo start = new PosInfo(row, col);
                    findSection(start, art);
                    answer1++;
                }
            }
        }
        // 적록 색약 그림 변경
        for (int row = 0; row < size; row++) {
            for (int col = 0; col < size; col++) {
                if (art[row][col] == 'G') {
                    art[row][col] = 'R';
                }
            }
        }
        // 적록 색약 visited 초기화
        visited = new boolean[size][size];
        // 적록 색약 구역 탐색
        for (int row = 0; row < size; row++) {
            for (int col = 0; col < size; col++) {
                if (!visited[row][col]) {
                    PosInfo start = new PosInfo(row, col);
                    findSection(start, art);
                    answer2++;
                }
            }
        }
        System.out.println(answer1 + " " + answer2);
    }

    private static void findSection(PosInfo posInfo, char[][] art) {
        // 이동 방향
        int[] dRow = {-1, 1, 0, 0};
        int[] dCol = {0, 0, -1, 1};
        // 색 확인
        char color = art[posInfo.row][posInfo.col];
        // 방문 처리 및 덱 셋팅
        visited[posInfo.row][posInfo.col] = true;
        Deque<PosInfo> posDeq = new ArrayDeque<>();
        posDeq.addLast(posInfo);
        // 탐색
        while (!posDeq.isEmpty()) {
            PosInfo now = posDeq.pollFirst();

            for (int i = 0; i < 4; i++) {
                int nextRow = now.row + dRow[i];
                int nextCol = now.col + dCol[i];
                // 범위 확인
                if (!canMove(nextRow, nextCol, art.length)) {
                    continue;
                }
                // 미방문이고 같은 색상이면 탐색
                if (!visited[nextRow][nextCol] &&
                    art[nextRow][nextCol] == color
                ) {
                    visited[nextRow][nextCol] = true;
                    posDeq.addLast(new PosInfo(nextRow, nextCol));
                }
            }
        }
    }

    private static boolean canMove(int row, int col, int size) {
        return (0 <= row && row < size) && (0 <= col && col < size);
    }
}

한 번에 적록색약과 일반인이 보는 구역을 구하는 로직으로 하는 게 더 좋은 코드인지 그림을 다시 적록색약이 보는 그림으로 변경하고 로직을 짜는 게 더 좋은 코드인지 고민을 했었습니다. 원래 메서드를 하나 더 만들어서 매개 변수에 따라 다르게 계산하는 로직을 짜려다 오히려 복잡하고 좋지 않다는 것임을 알게 되었습니다. 그래서 직관적으로 일반인 결과 계산과 그림을 바꾸고 적록색약의 결과를 구하는 것으로 짰습니다.