본문 바로가기
알고리즘

적록-색약

by 히포파타마스 2022. 5. 11.

적록-색약

백준 10026번 문제

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

 

10026번: 적록색약

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

www.acmicpc.net

 

 

 

 

1. 문제

문제

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

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

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

 

[그림 예]

RRRBB
GGBBB
BBBRR
BBRRR
RRRRR

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

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

 

입력

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

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

 

출력

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

 

예제 입력 1

5
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR

 

 

예제 출력 1

4 3

 

 

 

 

2. 풀이

입력받은 색으로 그림을 만든다.

추가로 적록색약이 보는 기준으로 그림을 하나더 만든다.

각각의 그림에 dfs를 사용해서 구역의 개수를 구한다.

 

■ 입력

[입력]

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();

    char[][] painting = new char[n][n];   //[1]
    boolean[][] check = new boolean[n][n];

    char[][] painting_CB = new char[n][n];   //[2]
    boolean[][] check_CB = new boolean[n][n];

    for (int i = 0; i < n; i++) {
        String line = scanner.next();
        for (int j = 0; j < n; j++) {
            char c = line.charAt(j);

            painting[i][j] = c;

            if (c == 'R') {   //[3]
                painting_CB[i][j] = 'G';
            } else {
                painting_CB[i][j] = c;
            }
        }
    }
    
    .
    .
    .
    
}

● [1] : 입력받은 색으로 구성될 그림과 dfs 메서드로 탐색된 원소를 체크하는 배열을 초기화한다.

● [2] : 적록색약이 보는 색으로 구성될 그림과 dfs 메서드로 탐색된 원소를 체크하는 배열을 초기화한다.

● [3] : 적록색약이 보는 색은 'R'과 'G'를 동일 시 하므로 'R'이 입력될 때 'G'로 변환해서 적록색약의 그림에 넣어준다. 

 

 

 

■ dfs

□ set

dfs() 메서드에서 다음 row와 col을 구하는 데 사용되는 배열

 

[set]

static int[] rowSet = {-1, 0, 1, 0};
static int[] colSet = {0, 1, 0, -1};

 

 

□ dfs

row와 col을 입력받고 해당 위치로부터 dfs를 사용해서 주어진 배열(painting[][])을 탐색하는 메서드

 

[dfs]

static public void dfs(int row, int col, int n, char[][] painting, boolean[][] check) {
    check[row][col] = true;   //[1]

    for (int i = 0; i < 4; i++) {
        int nextRow = row + rowSet[i];   //[2]
        int nextCol = col + colSet[i];
        if (nextRow < 0 || nextRow >= n || nextCol < 0 || nextCol >= n || check[nextRow][nextCol]
                || painting[nextRow][nextCol] != painting[row][col]) {   //[3]
            continue;
        }
        dfs(nextRow, nextCol, n, painting, check);   //[4]
    }
}

● [1] : dfs 메서드 실행 시 입력받은 row와 col에 해당하는 원소를 탐색했다고 판단하기 때문에 check[row][col]을 true로 설정

● [2] : 다음 row와 col을 구한다.

● [3] : 다음 row와 col이 범위에 맞는 값인지, 이미 탐색했는지, 이전의 색과 같은지를 판단해서 조건에 부합하지 않으면 탐색하지 않고 넘어간다.

● [4] : 앞의 조건에 걸리지않았다면 dfs()를 호출해서 다음 row와 col의 원소를 탐색

 

 

 

■ getResult

painting[][]과 check[][]를 받아서 구역의 개수를 반환하는 메서드

 

[getResult]

static public int getResult(char[][] painting, boolean[][] check) {
    int length = painting.length;
    int result = 0;

    for (int i = 0; i < length; i++) {
        for (int j = 0; j < length; j++) {
            if (check[i][j]) {   //[1]
                continue;
            }
            dfs(i, j, length, painting, check);   //[2]
            result++;   //[3]
        }
    }
    return result;
}

● [1] : 이미 탐색됬다면 다음 원소로 넘어간다.

● [2] : 탐색되지 않았다면 해당 위치로부터 dfs를 실행해서 연결된 구역을 탐색한다.

● [3] : 하나의 구역을 탐색할 때마다 반환될 결과에 +1을 더해준다.

 

 

 

■ 출력

각 그림에 getResult를 적용해서 구해진 구역의 개수를 출력한다.

 

[출력]

public static void main(String[] args) {
        
        .
        .
        .

        System.out.println(getResult(painting, check));
        System.out.println(getResult(painting_CB, check_CB));
    }
}

 

 

 

■ 전체 코드

[전체 코드]

public class Main {

    static int[] rowSet = {-1, 0, 1, 0};
    static int[] colSet = {0, 1, 0, -1};

    static public int getResult(char[][] painting, boolean[][] check) {
        int length = painting.length;
        int result = 0;

        for (int i = 0; i < length; i++) {
            for (int j = 0; j < length; j++) {
                if (check[i][j]) {
                    continue;
                }
                dfs(i, j, length, painting, check);
                result++;
            }
        }
        return result;
    }

    static public void dfs(int row, int col, int n, char[][] painting, boolean[][] check) {
        check[row][col] = true;

        for (int i = 0; i < 4; i++) {
            int nextRow = row + rowSet[i];
            int nextCol = col + colSet[i];
            if (nextRow < 0 || nextRow >= n || nextCol < 0 || nextCol >= n || check[nextRow][nextCol]
                    || painting[nextRow][nextCol] != painting[row][col]) {
                continue;
            }
            dfs(nextRow, nextCol, n, painting, check);
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();

        char[][] painting = new char[n][n];
        boolean[][] check = new boolean[n][n];

        char[][] painting_CB = new char[n][n];
        boolean[][] check_CB = new boolean[n][n];

        for (int i = 0; i < n; i++) {
            String line = scanner.next();
            for (int j = 0; j < n; j++) {
                char c = line.charAt(j);

                painting[i][j] = c;

                if (c == 'R') {
                    painting_CB[i][j] = 'G';
                } else {
                    painting_CB[i][j] = c;
                }
            }
        }

        System.out.println(getResult(painting, check));
        System.out.println(getResult(painting_CB, check_CB));
    }
}

 

 

 

댓글