[백준 18111] 마인크래프트 (C#, C++) - soo:bak
작성일 :
문제 링크
설명
이 문제는 마인크래프트에서 지형을 평탄화하여 모든 칸의 높이를 동일하게 만드는 데 필요한 최소 시간과 그때의 높이를 구하는 문제입니다.
세로 N
, 가로 M
크기의 집터에서 각 칸의 초기 높이가 주어지며, 인벤토리에 B
개의 블록이 있습니다.
목표는 블록을 추가하거나 제거하여 모든 칸을 같은 높이로 만들되, 작업 시간을 최소화하는 것입니다.
작업 종류
- 블록 제거: 한 칸에서 블록을 하나 제거하여 인벤토리에 넣습니다. 이 작업은
2초
가 소요됩니다. - 블록 추가: 인벤토리에서 블록을 꺼내 한 칸 위에 쌓습니다. 이 작업은
1초
가 소요됩니다.
제약 조건
- 사용할 수 있는 블록은 인벤토리에 있는 블록과 제거한 블록에 한정됩니다.
- 최종 높이는
0
이상256
이하이어야 합니다. - 가능한 작업 중 가장 짧은 시간이 소요되는 경우를 찾아야 하며, 만약 여러 높이가 동일한 시간이라면 가장 높은 높이를 선택해야 합니다.
접근법
- 높이는
0
부터256
까지, 혹은 입력된 지형의 최솟값과 최댓값 사이를 전부 확인합니다. - 각 가능한 높이
h
에 대해 다음 작업을 수행합니다:- 모든 칸을 순회하며 현재 높이와
h
의 차이를 계산합니다.- 현재 높이가
h
보다 크면 블록을 제거하고, 제거한 블록 수와 시간(2초
)을 누적합니다. - 현재 높이가
h
보다 작으면 블록을 추가하고, 필요한 블록 수와 시간(1초
)을 누적합니다.
- 현재 높이가
-
작업에 필요한 블록 수가 인벤토리에 있는 블록과 제거한 블록의 합보다 많으면 그 높이는 고려하지 않습니다.
\[\text{neededBlock} \leq B + \text{removedBlock}\] - 가능한 경우에 대해서는 소요되는 시간을 계산하고, 가장 짧은 시간과 가장 높은 높이를 기록합니다.
- 모든 칸을 순회하며 현재 높이와
Code
[ C# ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using System;
using System.Linq;
namespace Solution {
class Program {
static void Main(string[] args) {
var input = Console.ReadLine()!.Split().Select(int.Parse).ToArray();
var n = input[0], m = input[1], b = input[2];
var ground = new int[n * m];
var min = 256; var max = 0;
for (int i = 0; i < n; i++) {
var row = Console.ReadLine()!.Split().Select(int.Parse).ToArray();
for (int j = 0; j < m; j++) {
var h = row[j];
ground[i * m + j] = h;
min = Math.Min(min, h);
max = Math.Max(max, h);
}
}
var bestTime = int.MaxValue;
var bestHeight = 0;
for (int h = min; h <= max; h++) {
int add = 0, remove = 0;
foreach (var g in ground) {
if (g < h) add += h - g;
else if (g > h) remove += g - h;
}
if (add > b + remove) continue;
var time = add + 2 * remove;
if (time < bestTime || (time == bestTime && h > bestHeight)) {
bestTime = time;
bestHeight = h;
}
}
Console.WriteLine($"{bestTime} {bestHeight}");
}
}
}
[ C++ ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int len, width, inven;
cin >> len >> width >> inven;
int minT = 0;
int nbGround = len * width;
int* ground = new int[nbGround];
for (int i = 0; i < nbGround; i++) {
cin >> ground[i];
minT += ground[i] * 2;
}
int maxHeight = -1;
for (int height = 0; height <= 256; height++) {
int cntAdd = 0, cntSub = 0;
int block = inven;
for (int i = 0; i < nbGround; i++) {
if (ground[i] > height) {
cntSub += ground[i] - height;
block += ground[i] - height;
} else if (ground[i] < height) {
cntAdd += height - ground[i];
block -= height - ground[i];
}
}
if (block >= 0) {
int time = cntAdd + 2 * cntSub;
if (minT >= time) {
minT = time;
maxHeight = height;
}
}
}
cout << minT << " " << maxHeight << "\n";
return 0;
}