문제 출처 : https://www.acmicpc.net/problem/18111
언어 : Kotlin
문제 설명 :
팀 레드시프트는 대회 준비를 하다가 지루해져서 샌드박스 게임인 ‘마인크래프트’를 켰다. 마인크래프트는 1 × 1 × 1(세로, 가로, 높이) 크기의 블록들로 이루어진 3차원 세계에서 자유롭게 땅을 파거나 집을 지을 수 있는 게임이다.
목재를 충분히 모은 lvalue는 집을 짓기로 하였다. 하지만 고르지 않은 땅에는 집을 지을 수 없기 때문에 땅의 높이를 모두 동일하게 만드는 ‘땅 고르기’ 작업을 해야 한다.
lvalue는 세로 N, 가로 M 크기의 집터를 골랐다. 집터 맨 왼쪽 위의 좌표는 (0, 0)이다. 우리의 목적은 이 집터 내의 땅의 높이를 일정하게 바꾸는 것이다. 우리는 다음과 같은 두 종류의 작업을 할 수 있다.
- 좌표 (i, j)의 가장 위에 있는 블록을 제거하여 인벤토리에 넣는다.
- 인벤토리에서 블록 하나를 꺼내어 좌표 (i, j)의 가장 위에 있는 블록 위에 놓는다.
1번 작업은 2초가 걸리며, 2번 작업은 1초가 걸린다. 밤에는 무서운 몬스터들이 나오기 때문에 최대한 빨리 땅 고르기 작업을 마쳐야 한다. ‘땅 고르기’ 작업에 걸리는 최소 시간과 그 경우 땅의 높이를 출력하시오.
단, 집터 아래에 동굴 등 빈 공간은 존재하지 않으며, 집터 바깥에서 블록을 가져올 수 없다. 또한, 작업을 시작할 때 인벤토리에는 B개의 블록이 들어 있다. 땅의 높이는 256블록을 초과할 수 없으며, 음수가 될 수 없다.
- 첫째 줄에 N, M, B가 주어진다. (1 ≤ M, N ≤ 500, 0 ≤ B ≤ 6.4 × 107)
- 둘째 줄부터 N개의 줄에 각각 M개의 정수로 땅의 높이가 주어진다. (i + 2)번째 줄의 (j + 1)번째 수는 좌표 (i, j)에서의 땅의 높이를 나타낸다. 땅의 높이는 256보다 작거나 같은 자연수 또는 0이다.
- 첫째 줄에 땅을 고르는 데 걸리는 시간과 땅의 높이를 출력하시오. 답이 여러 개 있다면 그중에서 땅의 높이가 가장 높은 것을 출력하시오.
제한 사항 :
- 시간 제한 : 1초 (추가 시간 없음)
- 메모리 제한 : 1024MB
입출력 예 :
입력 | 출력 |
3 4 99 0 0 0 0 0 0 0 0 0 0 0 1 |
2 0 |
3 4 1 64 64 64 64 64 64 64 64 64 64 64 33 |
1 64 |
다른 사람의 풀이 :
import java.io.*
import java.util.StringTokenizer
import kotlin.math.max
import kotlin.math.min
fun main() {
val br = BufferedReader(InputStreamReader(System.`in`))
val bw = BufferedWriter(OutputStreamWriter(System.out))
val (n, m, b) = br.readLine().split(" ").map { it.toInt() }
val arr = Array(n) { IntArray(m) { 0 } }
repeat(n) {
val st = StringTokenizer(br.readLine(), " ")
for (i in 0 until m) arr[it][i] = st.nextToken().toInt()
}
var minY = 0
var maxY = 257
for (i in 0 until n) {
for (j in 0 until m) {
val height = arr[i][j]
minY = min(minY, height)
maxY = max(maxY, height)
}
}
var mining = Int.MAX_VALUE
var result = 0
for (i in minY .. maxY) {
var backpack = b
var time = 0
for (x in 0 until n) {
for (y in 0 until m) {
when {
arr[x][y] < i -> { // setting block
val d = i - arr[x][y]
time += d
backpack -= d
}
arr[x][y] > i -> { // mining block
val d = arr[x][y] - i
time += d * 2
backpack += d
}
}
}
}
if (backpack >= 0 && time <= mining) {
mining = time
result = i
}
}
bw.write("$mining $result")
bw.flush()
bw.close()
}
고민하며 풀어봤지만 막혀서 다른사람의 풀이를 참고했다.
arr의 최소값부터 최대값까지 반복문을 돌리는데, 현재 체크하는 i 보다 높다면 블록 제거, 낮다면 블록을 설치하는 작업을 수행한다. 팔때 2초, 설치할때 1초를 작업시간에 저장하며, 백팩에도 연산을 가해준다.
백팩의 값이 음수라면 i로 높이를 맞추는 것이 불가능한 것이므로 백팩의 값이 0 이상이거나, 현재 소모된 시간이 이전의 마이닝 시간보다 작다면 해당 값을 소모 시간으로 저장, 높이도 현재 높이로 저장해 출력한다.
자세한 해설 : https://uknowblog.tistory.com/14
'백준 > 문제' 카테고리의 다른 글
1012번: 유기농 배추 (0) | 2023.08.04 |
---|---|
1003번: 피보나치 함수 (0) | 2023.08.04 |
18110번: solved.ac (0) | 2023.08.03 |
7568번: 덩치 (0) | 2023.08.02 |
1676번: 팩토리얼 0의 개수 (0) | 2023.08.02 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!