[백준] 16929번 : Two Dots - JAVA [자바]

가오리·2023년 12월 8일
0
post-thumbnail

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


dfs 알고리즘 문제이다.

  1. 점들의 색을 입력 받는다.
  2. 0,0 부터 점들을 탐색한다.
  3. 아직 방문하지 않은 점이면 dfs 알고리즘을 실행한다.
  4. dfs 알고리즘에서는 현재 내 점에서 상하좌우를 살핀다.
  5. 같은 색인지 살핀다.
  6. 같은 색이고 아직 방문하지 않았으면 이 새로운 점으로 dfs 알고리즘을 넘긴다.
    6.1 이때, 같은 색이며 방문했던 점이면 사이클을 만들 수 있는지 확인한다.
    6.2 바로 전에서 왔던 점이면 건너뛴다.
    6.3 바로 전에서 왔던 점이 아니라면 이것은 사이클을 만들 수 있으므로 답을 출력한다.

여기서 중요한 포인트가 1. 같은 색인지 2. 방문했던 점인지 이 두 가지를 살펴보면 된다.

사이클이란 이미 방문했던 같은 색의 점을 다시 방문하는 것이다.

하지만 위의 정의대로라면 방금 왔던 점으로 되돌아가는 것도 사이클이 된다고 할 수 있다. 이러면 문제의 정의대로 4개 이상의 점으로 이뤄졌다고 할 수 없기 때문에 이 부분만 주의하면 된다.

즉, 인접한 점이 같은 색이며 방문했었지만 방금 왔던 점은 아니다.
-> 사이클이다.

위의 개념을 가지고 dfs 알고리즘으로 점들을 순환하며 사이클을 찾으면 종료하면 된다.

주의점으로 출력이 "Yes", "No" 이다.


public class bj16929 {

    public static boolean cycle = false;
    public static int M, N;
    public static Character[][] box;
    public static boolean[][] visited;
    static int[] xMove = {1, -1, 0, 0};
    static int[] yMove = {0, 0, -1, 1};

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

        String line = br.readLine();
        String[] split2 = line.split(" ");
        N = Integer.parseInt(split2[0]);
        M = Integer.parseInt(split2[1]);

        box = new Character[N][M];
        visited = new boolean[N][M];
        for (int i = 0; i < N; i++) {
            String line1 = br.readLine();
            char[] charArray = line1.toCharArray();
            for (int j = 0; j < M; j++) {
                box[i][j] = charArray[j];
            }
        }

        for (int i = 0; i < N; i++) {
            if (cycle) break;
            for (int j = 0; j < M; j++) {
                if (!visited[i][j]) {
                    if (cycle) break;
                    dfs(new spot(i, j), new spot(-1, -1));
                }
            }
        }

        if (cycle) {
            bw.write("Yes" + "\n");
        } else {
            bw.write("No" + "\n");
        }

        bw.flush();
        bw.close();
        br.close();
    }

    private static void dfs(spot start, spot last) {
        // 방문 처리
        visited[start.x][start.y] = true;

        // 나의 상하좌우 살피기
        for (int i = 0; i < 4; i++) {
            if (cycle) break;
            int newX = start.x + xMove[i];
            int newY = start.y + yMove[i];
            // 주어진 칸 안에 있는 곳 일때
            if (newX >= 0 && newX < N) {
                if (newY >= 0 && newY < M) {
                	// 같은 색이다.
                    if (box[newX][newY].equals(box[start.x][start.y])) {
                    	// 방문했었으며 방금 왔던 점이 아니다 -> 사이클
                        if ((visited[newX][newY]) && (last.x != newX || last.y != newY)) {
                            cycle = true;
                        } 
                        // 방문한 적 없으니 방문한다.
                        else if (!visited[newX][newY]) dfs(new spot(newX, newY), start);
                    }
                }
            }
        }
    }

    static class spot {
        int x;
        int y;

        spot(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
}
profile
가오리의 개발 이야기

0개의 댓글