[백준] 18111 마인크래프트
백준 18111 마인크래프트
https://www.acmicpc.net/problem/18111
18111번: 마인크래프트
팀 레드시프트는 대회 준비를 하다가 지루해져서 샌드박스 게임인 ‘마인크래프트’를 켰다. 마인크래프트는 1 × 1 × 1(세로, 가로, 높이) 크기의 블록들로 이루어진 3차원 세계에서 자유롭게
www.acmicpc.net
[문제]
집을 짓는데 집터를 다지는 문제이다.
집터의 땅의 높이를 일정하게 만들어 평평하게 만들어야 한다!
두 종류의 작업을 할 수 있다.
- 좌표 (i, j)의 가장 위에 있는 블록을 제거하여 인벤토리에 넣는다.
- 인벤토리에서 블록 하나를 꺼내어 좌표 (i, j)의 가장 위에 있는 블록 위에 놓는다.
1번 작업은 2초가 걸리며, 2번 작업은 1초가 걸린다.
최대한 빨리 땅 고르기 작업을 마쳐야 한다.
[입력]
첫째 줄에 N, M, B가 주어진다. (1 ≤ M, N ≤ 500, 0 ≤ B ≤ 6.4 × 107)
둘째 줄부터 N개의 줄에 각각 M개의 정수로 땅의 높이가 주어진다. (i + 2)번째 줄의 (j + 1)번째 수는 좌표 (i, j)에서의 땅의 높이를 나타낸다.
땅의 높이는 256보다 작거나 같은 자연수 또는 0이다.
[출력]
땅을 고르는 데 걸리는 시간과 땅의 높이를 차례로 출력한다.
[해결]
높이가 최소 0 이상이므로 0부터 최대 높이까지 탐색을 하면서, 최소 시간으로 땅을 평평하게 하는 높이를 찾아야 한다.
1. 최대 높이를 찾는 함수를 이용해서 탐색할 높이의 범위를 정한다.
2. 해당 높이로 땅을 평평하게 만들 때 걸리는 시간을 구한다.
3. 만약, block의 값이 음수라면, 해당 높이로 땅을 평평하게 할 수 없다는 것이므로 -1을 반환한다.
4. 걸리는 시간 중 최소 값을 출력한다.
#include <iostream>
using namespace std;
int n, m, b;
int map[501][501] = {0, };
//find max height
int find_max(){
int max = 0;
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
if (map[i][j] > max)
max = map[i][j];
}
}
return max;
}
//check the time
int check(int height){
int time = 0;
int block = b;
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
if (map[i][j] > height){
time += (map[i][j] - height) * 2;
block += map[i][j] - height;
}else if (map[i][j] < height){
time += height - map[i][j];
block -= height - map[i][j];
}
}
}
if (block < 0)
return -1;
return time;
}
int main(){
int max, height, time, tmp;
//input
cin >> n >> m >> b;
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++)
cin >> map[i][j];
}
max = find_max() + 1;
time = 1000000000;
height = 0;
while (--max >= 0){
tmp = check(max);
if (tmp != -1 && tmp < time){
time = tmp;
height = max;
}
}
cout << time << " " << height << endl;
return 0;
}