P2636. 치즈

wnajsldkf·2023년 3월 30일
0

Algorithm

목록 보기
39/58
post-thumbnail

설명

이 문제를 풀 때 고민한 것은 무엇을 기준으로 탐색할 것인가 이다.

만약 치즈를 기준으로 공기와 인접해있는지 탐색한다면, 공기가 있을 때 치즈가 녹지 않는다.-> 상하좌우 쭉~ 가서 벽과 인접해있는지 확인해야하나 했다.

그렇다면, 치즈가 아닌 외부 공기를 기준으로 상하좌우 방향을 DFS로 탐색한다.

일단 테두리는 치즈가 위치할 수 없으므로 (0,0)은 공기이므로 탐색할 수 있다. -> 굳이 왜 비워두었나 생각했다.

만약 공기가 탐색하다가 치즈를 만나면, 바로 공기로 변경해도 될까?
그렇지 않다.

바로 변경해버린다면
XXXX
O11X

이 경우에 볼드한 1도 공기에 닿게 된다.

따라서 탐색하다 만난 치즈는 2로 변경해두고,
녹지 않는 치즈가 있는지 확인하는 과정에서 공기(=0)으로 변경하면 된다.

코드

package P2636;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class P2636 {
    static int h, w;
    static int[][] cheese;
    static boolean[][] visited;
    static int count = 0;
    static int remains;

    static int[] dy = {0, 1, 0, -1};
    static int[] dx = {1, 0, -1, 0};
    static int n_y, n_x = 0;
    public static void main(String[] args) throws IOException {
        System.setIn(new FileInputStream("/Users/july/Desktop/ongoing/study/algorithm/P2636/input.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder();

        st = new StringTokenizer(br.readLine());

        h = Integer.parseInt(st.nextToken());
        w = Integer.parseInt(st.nextToken());

        cheese = new int[h][w];

        for (int i = 0; i < h; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < w; j++) {
                cheese[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        while (isCheese()) {
            count++;
            visited = new boolean[h][w];
            visited[0][0] = true;
            DFS(0, 0);  // 치즈가 없는 지점부터 확인한다.
        }

        sb.append(count);
        sb.append("\n");
        sb.append(remains);

        System.out.println(sb);
    }

    // 탐색한다.
    private static void DFS(int y, int x) {
        for (int i = 0; i < 4; i++) {
            n_y = y + dy[i];
            n_x = x + dx[i];

            // 범위 밖이면 넘어간다.
            if (n_y < 0 || n_y > h - 1 || n_x < 0 || n_x > w - 1) {
                continue;
            }

            // 방문했으면 넘어간다.
            if (visited[n_y][n_x]) {
                continue;
            }

            visited[n_y][n_x] = true;
            if (cheese[n_y][n_x] == 1) {
                cheese[n_y][n_x] = 2;
            } else {
                DFS(n_y, n_x);
            }
        }

    }

    private static boolean isCheese() {
        // 2로 표시된 부분은 공기와 맞닿은 치즈이므로, 공기로 바꿔줘야 한다.
        remains = 0;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if (cheese[i][j] == 2) {
                    cheese[i][j] = 0;
                    remains++;
                }
            }
        }

        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                // 1을 만난다 -> 탐색해야 한다.
                if (cheese[i][j] == 1) {
                    return true;
                }
            }
        }
        return false;
    }
}
profile
https://mywnajsldkf.tistory.com -> 이사 중

0개의 댓글