Post

적록 색약 - 10026

백준 골드 5

적록 색약

문제

적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다.

크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은 색상이라 한다)

예를 들어, 그림이 아래와 같은 경우에

1
2
3
4
5
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR

적록색약이 아닌 사람이 봤을 때 구역의 수는 총 4개이다. (빨강 2, 파랑 1, 초록 1) 하지만, 적록색약인 사람은 구역을 3개 볼 수 있다. (빨강-초록 2, 파랑 1)

그림이 입력으로 주어졌을 때, 적록색약인 사람이 봤을 때와 아닌 사람이 봤을 때 구역의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. (1 ≤ N ≤ 100)

둘째 줄부터 N개 줄에는 그림이 주어진다.

출력

적록색약이 아닌 사람이 봤을 때의 구역의 개수와 적록색약인 사람이 봤을 때의 구역의 수를 공백으로 구분해 출력한다.

예제 입력 1

1
2
3
4
5
6
5
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR

예제 출력 1

1
4 3

► Snippets

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
 * @Point 어떤 알고리즘 사용 - DFS, 인접행렬
 * 방문 체크 - 좌표 저장해야 함 - point 클래스
 * 시작 노드 - 0,0으로 불러서 r만 호출됨
 */
public class Main {

    //델타탐색
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};
    //n
    static int n;
    //n*n 인접행렬
    static String[][] g;
    //방문배열
    static boolean[][] visit;
    //카운트 변수 n0, n1
    static int n0, n1;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //n입력
        n = Integer.parseInt(br.readLine());
        //인접행렬 생성 방문배열 할당
        g = new String[n + 1][n + 1];

        String[] info = new String[n];
        for (int i = 0; i < n; i++) {
            info = br.readLine().split("");
            for (int j = 0; j < n; j++) {
                g[i][j] = info[j];
            }
        }

        int n0 = 0;
        int n1 = 0;
        int[] res = new int[2];
        //dfs 콜
        //개수 초기화 됨
        for (int i = 0; i < 2; i++) {
            visit = new boolean[n + 1][n + 1];

            for (int x = 0; x < g.length - 1; x++) {
                for (int y = 0; y < g[x].length - 1; y++) {
                    if (!visit[x][y]) {

                        dfs(x, y, i);
                        if (i == 0) {
                            n0++;
                        } else if (i == 1) {
                            n1++;
                        }
                    }
                }
            }
        }
        System.out.print(n0 + " " + n1);
    }

    //dfs
    private static void dfs(int x, int y, int i) {

        Stack<Point> stk = new Stack<>();
        stk.push(new Point(x, y));
        visit[x][y] = true;

        while (!stk.isEmpty()) {
            Point now = stk.pop();

            int nX = now.getX();
            int nY = now.getY();

            String a = g[nX][nY];

            for (int d = 0; d < 4; d++) {
                int newX = nX + dx[d];
                int newY = nY + dy[d];

                if (newX < 0 || newY < 0 || newX >= n || newY >= n) {
                    continue;
                }

                //인접노드
                String newNode = g[newX][newY];
                //0번째 색약없을때
                if (i == 0) {
                    if (a.equals(newNode) && !visit[newX][newY]) {
                        visit[newX][newY] = true;
                        stk.push(new Point(newX, newY));
                    }
                }
                //1번째 색약잇을 떄 //r,g 똑같을 때 처리
                //현재노드가 r이라면, r,g 다 갈 수 있다.
                else if (i == 1) {
                    if (a.equals("R") && g[newX][newY].equals("G") && !visit[newX][newY]
                            ||
                            a.equals("R") && g[newX][newY].equals("R") && !visit[newX][newY]
                            ||
                            a.equals("G") && g[newX][newY].equals("R") && !visit[newX][newY]
                            ||
                            a.equals("G") && g[newX][newY].equals("G") && !visit[newX][newY]
                            ||
                            a.equals("B") && g[newX][newY].equals("B") && !visit[newX][newY]) {
                        visit[newX][newY] = true;
                        stk.push(new Point(newX, newY));
                    }
                   }
                }
            }
        }
    }

    //pair
    public static class Point {
        private final int x, y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }
    }
}

► 시간 소요한 것

최근 그래프 문제를 많이 풀었어서, 나름 쉽게 풀 수 있었다.

근데 또 실수한 것이 있다.

1. 방문배열 초기화를 안 해줬다.

  • 적록색약인 사람과 적록색약이 아닌 사람은 같은 그림을 봐도 다르게 인식한다.
    • 따라서 각 DFS는 다르게 수행되어야 한다. → 방문배열을 for문 내에서 초기화해줘야 한다.
This post is licensed under CC BY 4.0 by the author.