[백준] 16724 - 피리 부는 사나이

DongJunKim99·2023년 7월 27일
post-thumbnail

[Gold III] 피리 부는 사나이 - 16724

문제 링크

분류

자료 구조, 깊이 우선 탐색, 분리 집합, 그래프 이론, 그래프 탐색

문제 설명

피리 부는 사나이 성우는 오늘도 피리를 분다.

성우가 피리를 불 때면 영과일 회원들은 자기도 모르게 성우가 정해놓은 방향대로 움직이기 시작한다. 성우가 정해놓은 방향은 총 4가지로 U, D, L, R이고 각각 위, 아래, 왼쪽, 오른쪽으로 이동하게 한다.

이를 지켜보던 재훈이는 더 이상 움직이기 힘들어하는 영과일 회원들을 지키기 위해 특정 지점에 ‘SAFE ZONE’ 이라는 최첨단 방음 시설을 만들어 회원들이 성우의 피리 소리를 듣지 못하게 하려고 한다. 하지만 예산이 넉넉하지 않은 재훈이는 성우가 설정해 놓은 방향을 분석해서 최소 개수의 ‘SAFE ZONE’을 만들려 한다.

성우가 설정한 방향 지도가 주어졌을 때 재훈이를 도와서 영과일 회원들이 지도 어느 구역에 있더라도 성우가 피리를 불 때 ‘SAFE ZONE’에 들어갈 수 있게 하는 ‘SAFE ZONE’의 최소 개수를 출력하는 프로그램을 작성하시오.

입력

첫 번째 줄에 지도의 행의 수를 나타내는 N(1 ≤ N ≤ 1,000)과 지도의 열의 수를 나타내는 M(1 ≤ M ≤ 1,000)이 주어진다.

두 번째 줄부터 N개의 줄에 지도의 정보를 나타내는 길이가 M인 문자열이 주어진다.

지도 밖으로 나가는 방향의 입력은 주어지지 않는다.

출력

첫 번째 줄에 ‘SAFE ZONE’의 최소 개수를 출력한다.

풀이

입력으로 주어지는 지도에서 밖으로 나가는 방향의 입력은 주어지지 않는 다고 했으니, 순환 구조가 존재할 것이라고 판단하였다. 순환 구조에서는 아무 한 점이나 SAFE ZONE으로 지정하면 되겠다고 생각하여서 순환 구조를 발견할때마다 출력할 변수를 +1 해주고, 기존에 존재하는 순환구조를 방문하는 경우에는 변수의 크기를 키우지 않는 방식으로 해결할 수 있었다.


import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    public static final BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));
    int N;
    int M;
    String[] map;
    int[][] visited;
    int[][] group;
    int[] dx = {-1, 0, 1, 0};
    int[] dy = {0, -1, 0, 1};
    public static HashMap<Character, Integer> convertTable = new HashMap<>() {
        {
            put('U', 0);
            put('L', 1);
            put('D', 2);
            put('R', 3);
        }
    };
    int answer;
    int index;
    public static void main(String[] args) {
        Main main = new Main();
        try {
            main.init();
            main.solution();
        } catch (IOException e) {
            System.out.println("exception during I/O");
        }
    }


    void init() throws IOException {
        int[] inputArray = Arrays.stream(BR.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        N = inputArray[0];
        M = inputArray[1];

        map = new String[N];
        for (int i = 0; i < N; i++) {
            map[i] = BR.readLine();
        }

        visited = new int[N][M];
        group = new int[N][M];
        answer = 0;
        index = 0;
    }

    void solution() throws IOException {

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (visited[i][j] == 0) {
                    group[i][j] = index;
                    dfs(i, j);
                    index += 1;
                }
            }
        }
        System.out.println(answer);
    }

    void dfs(int i, int j) {
        if (visited[i][j] == 1) {
            if (group[i][j] == index) {
                answer += 1;
            }
            return;
        }
        visited[i][j] = 1;
        group[i][j] = index;
        int[] nextNode = getNextNode(i, j);
        dfs(nextNode[0], nextNode[1]);

    }

    int[] getNextNode(int i, int j) {
        Integer direction = convertTable.get(map[i].charAt(j));
        return new int[]{i + dx[direction], j + dy[direction]};

    }

}

0개의 댓글