문제 풀이/백준

[백준] 16918번. 봄버맨(JAVA)

27200 2024. 9. 26. 21:22

문제

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


풀이

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

public class Main {
    static String[][] arr;
    static int[][] bombs;

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

        // 첫 번째 줄에서 행(row), 열(col), 시간(time) 입력 받음
        st = new StringTokenizer(br.readLine());
        int row = Integer.parseInt(st.nextToken());
        int col = Integer.parseInt(st.nextToken());
        int time = Integer.parseInt(st.nextToken());

        // 배열 초기화
        arr = new String[row][col];
        bombs = new int[row][col]; // 폭탄의 타이머 관리 배열

        // 초기 맵 상태 입력
        for (int i = 0; i < row; i++) {
            String s = br.readLine();
            for (int j = 0; j < col; j++) {
                String temp = s.substring(j, j + 1); // 각 칸에 대해 문자 추출
                arr[i][j] = temp;

                if (temp.equals("O")) { // 폭탄이 설치된 곳은 'O'
                    bombs[i][j] = 2; // 폭탄 타이머: 3초 후 폭발
                }
            }
        }

        // 시간에 따른 처리
        for (int t = 2; t <= time; t++) {
            time(); // 폭탄 타이머 감소
            full();
            ArrayList<int[]> tempList = check(); // 폭발할 폭탄 체크
            play(tempList); // 폭발 처리
        }

        // 결과 출력
        answer();
    }

    // 맵 상태 출력
    private static void answer() {
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j]);
            }
            System.out.println();
        }
    }
    
    // 모든 빈 공간에 폭탄 설치 (2초마다)
    private static void full() {
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                if (arr[i][j].equals(".")) { // 빈 공간일 경우
                    arr[i][j] = "O"; // 폭탄 설치
                    bombs[i][j] = 3; // 새로 설치된 폭탄 타이머는 3초
                }
            }
        }
    }

    // 폭탄 타이머 감소
    private static void time() {
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                if (arr[i][j].equals("O")) {
                    bombs[i][j]--; // 타이머 감소
                }
            }
        }
    }

    // 폭발할 폭탄 체크
    private static ArrayList<int[]> check() {
        ArrayList<int[]> list = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                if (arr[i][j].equals("O") && bombs[i][j] == 0) { // 타이머가 0인 폭탄을 체크
                    int[] tempArr = {i, j};
                    list.add(tempArr);
                }
            }
        }
        return list;
    }

    // 폭발 처리 (동서남북)
    private static void play(ArrayList<int[]> list) {
        for (int[] tempArr : list) {
            int row = tempArr[0]; // 폭탄의 행 위치
            int col = tempArr[1]; // 폭탄의 열 위치

            // 현재 폭탄 폭발
            arr[row][col] = ".";

            // 동쪽 처리 (열 + 1)
            if (col + 1 < arr[0].length) {
                arr[row][col + 1] = ".";
            }

            // 서쪽 처리 (열 - 1)
            if (col - 1 >= 0) {
                arr[row][col - 1] = ".";
            }

            // 남쪽 처리 (행 + 1)
            if (row + 1 < arr.length) {
                arr[row + 1][col] = ".";
            }

            // 북쪽 처리 (행 - 1)
            if (row - 1 >= 0) {
                arr[row - 1][col] = ".";
            }
        }
    }
}

 

문제의 입력을 제대로 읽는 것을 습관화하자! -> 또 띄어쓰기가 없는 것을 보지 않고 st.nextToken()으로 받아버리는 실수를 했다 ㅠ

 

문제에 대한 이해만 정확하면 해결이 어려운 문제는 아닌 것 같다. 다만 시작 시에만 조건이 따로 존재한다는 점을 인식하자.

따라서 시간은 2초부터 카운트하게 된다. 이에 대해 답이 바뀌는 상황은 없으므로 마지막에 정답 배열을 출력하는 것으로 마무리한다. 다만, 정답배열(2차원 배열)을 출력하는 함수를 따로 만들어서 구현했다. 이는 디버깅을 사용하지 않고, 배열을 출력하여 결과를 보고 싶을 때 코드를 단순화하는데 도움을 줬다.

 

코드를 이해해 보면 입력을 받을 때 초기 2초부터 시작할 것이기 때문에 폭발 타이머를 2로 두고 입력을 받는다.

이후 시간의 흐름에 따른 동작은 다음과 같다.

1. 시간을 먼저 감소시킨다.

2. 채워지지 않은 폭탄의 장소를 채운다.(시간을 먼저 감소시키지 않는다면 여기서 입력되자마자 시간이 2로 줄어드는 문제가 발생하게 된다.)

3. 폭발할 폭탄의 위치를 먼저 체크해서 넣어둔다.(full함수와 통일한다면 훨씬 반복이 줄어드는 코드가 될 것 같기는 하다.)(별도의 리스트로 만들어서 관리하는 이유는 이렇게 하지 않는다면 먼저 터진 폭탄에 의해 초기화되어 터지지 않을 가능성이 있기 때문이다.)

4. 마지막으로 폭탄들을 처리해 준다.