https://www.acmicpc.net/problem/18111
import java.io.*;
import java.util.*;
class Main {
public static void main(String[] args) throws Exception {
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[][] map = new int[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
System.out.println(solve(N, M, B, map));
}
static Result solve(int N, int M, int B, int[][] map) {
// 1. 맵의 최대 높이와 최소 높이 구하기
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
max = Math.max(max, map[i][j]);
min = Math.min(min, map[i][j]);
}
}
PriorityQueue<Result> pq = new PriorityQueue<Result>();
for (int i = min; i <= max; i++) {
int time = 0;
int block = B;
int diff = 0;
for (int j = 0; j < N; j++) {
for (int k = 0; k < M; k++) {
// 1. i보다 맵이 낮은 경우, 블록을 쌓아야 함.
if (map[j][k] < i) {
diff = i - map[j][k];
time += diff;
block -= diff;
}
// 2. i보다 맵이 높은 경우 맵을 깎아야 함, 즉 블록을 지워야함
else if (map[j][k] > i) {
diff = map[j][k] - i;
time += 2 * diff;
block += diff;
}
}
}
if (block >= 0) {
//i가 곧 height를 의미함.
pq.add(new Result(time, i));
break;
}
}
return pq.poll();
}
static class Result implements Comparable<Result> {
int time;
int height;
Result(int time, int height) {
this.time = time;
this.height = height;
}
@Override
public int compareTo(Result o) {
//시간이 같은 경우, 높이가 높은 경우가 우선순위가 높게
if (this.time == o.time) {
return Integer.compare(o.height, this.height);
}
// 시간이 다르면, 시간이 가장 짧은 경우의 우선순위를 높게
return Integer.compare(this.time, o.time);
}
@Override
public String toString() {
return time + " " + height;
}
}
}
더해진 값만큼의 시간
이 걸리고, 값을 뺄 떄는 뺀 값의 2배만큼 시간
이 걸린다.높이가 가장 높은 경우
가 정답이 된다.1) 블록을 제거해서 인벤토리에 넣는 동작
, 2) 인벤토리에서 블록을 꺼내서 놓는 동작
두가지를 할 수 있다.그 다음 블록을 제거해서 인벤토리에 넣는다면 블록
이 생길 수 있다는 것이다.다음과 같은 상황을 가정하자.
- 이중 for문을 통해 2차원 배열을 접근한다.
- 예를 들어 [0, 1]시점에는 블록을 못 놓을 수 있더라도, [0, 2]에서 블록을 캔다면 [0, 1]시점은 블록을 놓을 수 있다.
브루트포스
로 문제를 해결해야 한다.브루트포스
를 수행할 하한은 맵의 최소값
, 상한은 맵의 최대값
이다. 그 이외의 경우에 대해선 생각할 필요가 없다.브루트포스
를 통해 구해진 결과값은 문제의 조건에 맞도록 Result
객체에 compareTo
를 구현한 후, priorityQueue
에 넣도록 하였다.dp
와 더불어 브루트포스
도 익숙하지 않았다. min ~ max
범위에서 만들어지는 결과를 다뤄야한다는 아이디어를 떠올리지 못해 풀이를 찾아봤다.pq
는 이 문제에서 오버스펙인 느낌이 있는 것 같다. 단순히 현재 도출된 값과 이전 값을 비교하는 로직만 추가해도 충분히 해결할 수 있어보인다.