Coding Test/Baekjoon

백준/10026번/Java - 적록색약 (DFS)

grogu.... 2023. 10. 4. 20:43

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

 

10026번: 적록색약

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

www.acmicpc.net


https://seungboo.tistory.com/27

 

백준/2606번/Java - 바이러스 (DFS)

https://www.acmicpc.net/problem/2606 2606번: 바이러스 첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하인 양의 정수이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트

seungboo.tistory.com

위의 2606번 문제와 마찬가지로 DFS를 활용하여 풀 수 있는 문제이다.

하지만 난이도는 조금 더 높다.

R, G, B의 위치를 char 타입의 이차원 배열에 나타내야 한다.

2606번 문제의 경우, 노드와 간선의 연결관계를 인접리스트에 저장하여, 해당 인접리스트를 for문으로 돌면서 저장된 노드라면 이동을 할 수 있도록 구현하였다.

하지만 이번 문제는 N x N 크기의 이차원 배열 위에서 이동하여야 하므로, 상,하,좌,우 방향으로 모두 이동할 수 있는 지 검사하여야 한다.

따라서 상하좌우 방향의 이동을 나타내는 dx, dy  배열을 활용하였다.

이동방향은 상하좌우 4가지 이므로 0~3까지 반복문을 돌며 각각의 이동방향에 따른 다음 행과 열의 위치를 구하고

해당 위치가 배열을 벗어나지 않았는지, 해당 위치의 색깔이 이동이 가능한 색깔인지 검사할 수 있다.

검사를 모두 통과하면 탐색을 이어가면 된다!

import java.io.*;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {

    static boolean[][] visited;
    static char[][] board;
    static char[][] board_blind;

    static int count = 0;
    static int count_blind = 0;
    static int N;
    //행 이동 상하좌우
    static int[] dx = {-1, 1, 0, 0};
    //열 이동 상하좌우
    static int[] dy = {0, 0, -1, 1};

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

        N = Integer.parseInt(br.readLine());
        board = new char[N][N];
        board_blind = new char[N][N];
        visited = new boolean[N][N];

        /*
        2차원 배열에 R, G, B를 배치한다.
        i=행 j=열
         */
        for(int i=0; i<N; i++) {
            String s = br.readLine();
            for(int j=0; j<N; j++) {
                char c = s.charAt(j);
                if(c == 'G') {
                    board[i][j] = c;
                    board_blind[i][j] = 'R';
                } else {
                    board[i][j] = c;
                    board_blind[i][j] = c;
                }
            }
        }

        /*
        탐색을 한다. -> 탐색이 종료되면 구역이 1개 나온 것.
        탐색은 (0,0)에서 시작
         */
        for(int x=0; x<N; x++) {
            for(int y=0; y<N; y++) {
                if(!visited[x][y]){
                    dfs(x, y);
                    count++;
                }
            }
        }

        visited = new boolean[N][N]; //방문 배열 초기화.

        for(int x=0; x<N; x++) {
            for(int y=0; y<N; y++) {
                if(!visited[x][y]){
                    dfs_blind(x, y);
                    count_blind++;
                }
            }
        }

        System.out.println(count + " " + count_blind);
    }

    private static void dfs(int x, int y) {
        //이미 방문한 칸이거나 색이 다른 칸이면 방문할 수 없다.
        if(visited[x][y]) {
            return;
        }
        visited[x][y] = true;
        for(int i=0; i<4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(nx < 0 || nx >= N || ny < 0 || ny >= N) continue;
            if(board[nx][ny] == board[x][y]) dfs(nx, ny);

        }


    }
    private static void dfs_blind(int x, int y) {
        if(visited[x][y]){
            return;
        }
        visited[x][y] = true;
        //상단 이동
        for(int i=0; i<4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(nx < 0 || nx >= N || ny < 0 || ny >= N) continue;
            if(board_blind[nx][ny] == board_blind[x][y]) dfs_blind(nx, ny);

        }
    }
}