백준 마인크래프트

KIMYEONGJUN·2026년 3월 17일
post-thumbnail

문제

내가 생각했을때 문제에서 원하는부분

첫째 줄에 N, M, B가 주어진다. (1 ≤ M, N ≤ 500, 0 ≤ B ≤ 6.4 × 107)
둘째 줄부터 N개의 줄에 각각 M개의 정수로 땅의 높이가 주어진다.
(i + 2)번째 줄의 (j + 1)번째 수는 좌표 (i, j)에서의 땅의 높이를 나타낸다.
땅의 높이는 256보다 작거나 같은 자연수 또는 0이다.

첫째 줄에 땅을 고르는 데 걸리는 시간과 땅의 높이를 출력하시오.
답이 여러 개 있다면 그중에서 땅의 높이가 가장 높은 것을 출력하시오.

내가 이 문제를 보고 생각해본 부분

먼저 입력으로 땅 크기 N, M과 초기 인벤토리 블록 수 B를 받는다.
다음으로 땅 각 칸의 높이를 2차원 배열에 저장하면서 최솟값과 최댓값을 찾아 높이 조절 범위를 설정한다.
가능한 땅 높이 후보인 minHeight부터 maxHeight까지 모두 시도하면서, 각각의 후보 높이에 맞추기 위한 작업 시간을 계산한다.
각 칸의 현재 높이와 후보 높이의 차이를 계산하여 다음을 처리한다:
높이가 더 높으면 블록을 제거해 인벤토리에 넣고 2초 걸림
높이가 더 낮으면 인벤토리에서 블록 꺼내 쌓아 1초 걸림
작업 중 인벤토리 블록 수가 음수가 되면 불가능한 경우이므로 그 후보 높이는 건너뛴다.
가능한 후보 높이 중 작업 시간이 가장 적은 경우를 기록하고, 시간이 같으면 더 높은 땅 높이를 선택한다.
반복이 끝나면 최소 시간을 출력하고, 그때의 땅 높이를 출력한다.
이 문제는 모든 후보 높이를 브루트 포스로 탐색하는 문제로, 입력 조건(N ≤ 500) 내에서 충분히 동작한다.

코드로 구현

package baekjoon.baekjoon_33;

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

// 백준 18111번 문제
public class Main1329 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        int B = Integer.parseInt(st.nextToken());
        int[][] land = new int[N][M];
        int minHeight = 256;
        int maxHeight = 0;

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                land[i][j] = Integer.parseInt(st.nextToken());
                if (land[i][j] < minHeight) minHeight = land[i][j];
                if (land[i][j] > maxHeight) maxHeight = land[i][j];
            }
        }

        int resultTime = Integer.MAX_VALUE;
        int resultHeight = 0;

        // 가능한 높이 범위 내에서 모두 검사
        for (int h = minHeight; h <= maxHeight; h++) {
            int time = 0;
            int inventory = B;
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    int diff = land[i][j] - h;
                    if (diff > 0) {
                        // 땅에서 블록 제거 (2초, 블록 인벤토리에 추가)
                        time += diff * 2;
                        inventory += diff;
                    } else if (diff < 0) {
                        // 인벤토리에서 블록 꺼내서 쌓기 (1초)
                        time += (-diff);
                        inventory -= (-diff);
                    }
                }
            }

            // 인벤토리 블록이 음수이면 불가능한 높이
            if (inventory < 0)
                continue;

            // 최소 시간 갱신, 동일하면 더 높은 높이 선택
            if (time < resultTime || (time == resultTime && h > resultHeight)) {
                resultTime = time;
                resultHeight = h;
            }
        }

        System.out.println(resultTime + " " + resultHeight);
        br.close();
    }
}

마무리

코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.

profile
Junior backend developer

0개의 댓글