[실전 문제] CHEEZE

2021. 3. 8. 12:40코딩 테스트/실전 문제

1. 문제

아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색 으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모칸에 엑스친 부분)에는 치즈가 놓여 있지 않으며 치즈에는 하나 이상의 구멍이 있을 수 있다.

이 치즈를 공기 중에 놓으면 녹게 되는데 공기와 접촉된 칸은 한 시간이 지나면 녹아 없어진다. 치즈의 구멍 속에는 공기가 없지만 구멍을 둘러싼 치즈가 녹아서 구멍이 열리면 구멍 속으로 공기가 들어 가게 된다. <그림 1>의 경우, 치즈의 구멍을 둘러싼 치즈는 녹지 않고 ‘c’로 표시된 부분만 한 시간 후 에 녹아 없어져서 <그림 2>와 같이 된다.

다시 한 시간 후에는 <그림 2>에서 ‘c’로 표시된 부분이 녹아 없어져서 <그림 3>과 같이 된다.

<그림 3>은 원래 치즈의 두 시간 후 모양을 나타내고 있으며, 남은 조각들은 한 시간이 더 지나면 모두 녹아 없어진다. 그러므로 처음 치즈가 모두 녹아 없어지는 데는 세 시간이 걸린다. <그림 3>과 같이 치즈가 녹는 과정에서 여러 조각으로 나누어 질 수도 있다.

입력으로 사각형 모양의 판의 크기와 한 조각의 치즈가 판 위에 주어졌을 때, 공기 중에서 치즈가 모두 녹아 없어지는 데 걸리는 시간과 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수 를 구하는 프로그램을 작성하시오.


입력

첫째 줄에는 사각형 모양 판의 세로와 가로의 길이가 양의 정수로 주어진다. 세로와 가로의 길이는 최대 100이다. 판의 각 가로줄의 모양이 윗 줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다. 치즈가 없는 칸은 0, 치즈가 있는 칸은 1로 주어 지며 각 숫자 사이에는 빈칸이 하나씩 있다.

출력

첫째 줄에는 치즈가 모두 녹아서 없어지는 데 걸리는 시간을 출 력하고, 둘째 줄에는 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수를 출력한다.

예제 입력

13 12
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0
0 1 1 1 0 0 0 1 1 0 0 0
0 1 1 1 1 1 1 0 0 0 0 0
0 1 1 1 1 1 0 1 1 0 0 0
0 1 1 1 1 0 0 1 1 0 0 0
0 0 1 1 0 0 0 1 1 0 0 0
0 0 1 1 1 1 1 1 1 0 0 0
0 0 1 1 1 1 1 1 1 0 0 0
0 0 1 1 1 1 1 1 1 0 0 0
0 0 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0

예제 출력

3
5

 

 

 

2. 풀이

이 문제는 DFS를 이용하여 해결할 수 있다. 공기를 기준으로 깊이 우선 탐색을 하여 외부 공기과 맞닿은 치즈를 찾아야한다. 판의 테두리는 치즈가 위치할 수 없기에 모두 공기이다.

 

단, 주의해야할 점은 바로 치즈를 녹이면 안된다는 점이다. 예를 들어 '011' 구간이 있을 때, 첫 번째 0은 공기이므로 중간의 1을 0을 바로 만들어버리면 '001'로 세 번째 1의 입장에서 외부 공기와 맞닿아 있다고 판단해버린다.

 

따라서 외부 공기와 맞닿은 치즈를 바로 0으로 만들어버리는 것이 아닌, 2로 만들어 '1초 뒤 녹을 예정인 치즈'로 만들어주어야한다. 즉, 공기와 맞닿는 치즈를 2로 만들어주고, 1초 뒤 2를 0으로 변경해주는 방법으로 진행하면 해결할 수 있다.

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

public class Main {

    private static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    private static final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

    private static int n;
    private static int m;

    private static int[][] arr;
    private static boolean[][] isVisited;

    private static int[] dy = {0, 1, 0, -1};
    private static int[] dx = {1, 0, -1, 0};

    private static int cheeseCnt;
    private static int time;

    public static void main(String[] args) throws IOException {

        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());

        arr = new int[n][m];
        isVisited = new boolean[n][m];
        for(int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            for(int j = 0; j < m; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        while(isCheese()) {
            for(boolean tmp[] : isVisited) {
                Arrays.fill(tmp, false);
            }
            cheeseCnt = 0;
            dfs(0,0);
            time++;
        }

        bw.write(time + "\n" + cheeseCnt);
        br.close();
        bw.flush();
        bw.close();
    }

    private static boolean isCheese() {
        // 공기와 맞닿은 치즈 삭제
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(arr[i][j] == 2) {
                    arr[i][j] = 0;
                }
            }
        }

        // 치즈가 남아 있는지 확인
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(arr[i][j] == 1) {
                    // 치즈가 있을 경우
                    return true;
                }
            }
        }

        return false;
    }

    // 공기에 맞닿은 치즈 탐색
    private static void dfs(int i, int j) {
        isVisited[i][j] = true;

        for(int k = 0; k < 4; k++) {
            int ny = i + dy[k];
            int nx = j + dx[k];

            if(ny >= 0 && ny < n && nx >= 0 && nx < m) {
                if(!isVisited[ny][nx]) {
                    isVisited[ny][nx] = true;
                    if(arr[ny][nx] == 1) {
                        arr[ny][nx] = 2;
                        cheeseCnt++; //지워질 치즈 수
                    } else {
                        dfs(ny, nx);
                    }
                }
            }
        }
    }

}
728x90

'코딩 테스트 > 실전 문제' 카테고리의 다른 글

[실전 문제] TOMATO  (0) 2021.03.08
[실전 문제] ROBOT  (0) 2021.03.08
[실전 문제] 폭발물 설치  (0) 2021.03.04
[실전 문제] 파티  (0) 2021.03.04