알고리즘/그래프

[BoJ] 백준 10026 - 적록색약 풀이

송승현(SSH) 2022. 7. 16. 18:47

1. 문제

https://www.acmicpc.net/problem/10026

 

10026번: 적록색약

적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다. 크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록)

www.acmicpc.net

 

 

 

2. 풀이

깊이 우선 탐색(DFS)의 응용이다. 큰 응용이 아니라 정답 비율이 높은 것 같다.
DFS의 기본적인 내용은 아래의 포스팅을 참고하면 많은 도움이 된다.

https://velog.io/@songyw0517/DFS%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80

 

DFS란 무엇인가?

깊이 우선 탐색이라고도 부르며, 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘 입니다.그림에서 보이듯 시작노드를 방문하고 연결된 다음 노드에 방문, 그 다음 연결된 노드에 방문...

velog.io

 

이 문제를 접근할 때 두 가지의 경우로 접근했다. 

1) 적록색약이 아닌 사람

    적록 색약이 아닌 사람의 경우 R, G, B 각각을 다 다른 문자로 생각하고 구역을 계산하면 된다. 우선 2차원 배열을 만들어 입력 값을 저장해준 후 이차원 배열을 하나씩 탐색하면서 DFS 함수를 실행한다. DFS 함수 안에서 탐색할 때는 상하좌우로 인접해 있는 경우에 같은 구역에 속한다고 했으므로 상하좌우로 움직일 수 있는 dx, dy 배열을 만들고 각각을 더해주면서 탐색한다. 이때 조건은 더했을 때의 값이 배열을 벗어나면 안되고 Main 함수에서 반복 한 바퀴를 돌았을 때 하나의 구역이 카운트 되야 하기 때문에 현재 문자와 다음 탐색할 문자가 같을 경우에만 dfs 함수를 실행한다.

 

2) 적록색약인 사람

    기본적인 로직은 (1)과 같다. 단 적록색약인 사람은 R과 G를 같은 문자로 인식하기 때문에 dfs 함수 안에서 (1) 현재 문자가 R 이고 다음 탐색할 문자가 G인 경우, (2) 현재 문자가 G이고 다음 탐색할 문자가 R인 경우에도 dfs 함수를 실행해야 한다.

 

 

3. 소스코드

package dfs;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

class red_green_weakness {
    static int N;
    static char[][] map;
    static boolean[][] visited;
    static int[] dx = {1, -1, 0, 0};
    static int[] dy = {0, 0, 1, -1};

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        N = Integer.parseInt(br.readLine());
        map = new char[N][N];
        visited = new boolean[N][N];
        String input;
        int result1 = 0;
        int result2 = 0;

        for (int i = 0; i < N; i++) {
            input = br.readLine();
            for (int j = 0; j < N; j++) {
                map[i][j] = input.charAt(j);
            }
        }

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(!visited[i][j]) {
                    dfs_no(i, j);
                    result1 += 1;
                }
            }
        }

        visited = new boolean[N][N];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(!visited[i][j]) {
                    dfs_yes(i, j);
                    result2 += 1;
                }
            }
        }

        bw.write(Integer.toString(result1) + " " + Integer.toString(result2));
        bw.flush();
        bw.close();
        br.close();
    }

    private static void dfs_yes(int x, int y) {
        visited[x][y] = true;

        for (int i = 0; i < 4; i++) {
            int xf = x + dx[i];
            int yf = y + dy[i];

            if (xf >= 0 && yf >= 0 && xf < N && yf < N && !visited[xf][yf]) {
                if((map[x][y] == map[xf][yf]) || (map[x][y] == 'R' && map[xf][yf] == 'G') || (map[x][y] == 'G' && map[xf][yf] == 'R'))
                    dfs_yes(xf, yf);
            }
        }
    }

    private static void dfs_no(int x, int y) {
        visited[x][y] = true;

        for (int i = 0; i < 4; i++) {
            int xf = x + dx[i];
            int yf = y + dy[i];

            if (xf >= 0 && yf >= 0 && xf < N && yf < N && !visited[xf][yf] && (map[x][y] == map[xf][yf])) {
                dfs_no(xf, yf);
            }
        }
    }
}