문제
격자에 넴모가 배치되어있고 좌표를 설정하여 레이저를 배치했을 때 몇마리의 넴모가 사라지는 지 구하는 문제이다.
풀이
먼저 넴모의 배치를 보면 중력을 받기 때문에 한 위치를 잡았을 때 그 위치보다 아래층에 넴모가 무조건 배치되어있다.
레이저의 영향을 받는 넴모는 본문에서는 어렵게 설명하였는데 결국 레이저의 위치를 기준으로 오른쪽과 위쪽에 넴모들이 영향을 받는다.
따라서 문제를 해결하려면 레이저의 위치를 기준으로 해당 위치 + 오른쪽 + 위쪽의 넴모의 개수를 카운트하면된다.
val (N, Q) = readLine().split(" ").map { it.toInt() }
val states = readLine().split(" ").map { it.toInt() }
val maxNum = states.maxOrNull()
먼저 필요한 정보를 입력받는다.
states 는 넴모의 위치를 나타내는 변수로 [3, 3, 2] 일경우 1층 3개 2층 3개 3층 2개의 넴모로 이루어져있다는 걸 의미한다.
Q는 레이저의 개수를 의미하므로 Q만큼 반복한다
repeat(Q) {
var answer = 0
val(x, y) = readLine().split(" ").map { it.toInt() }
var start = 0
var end = N
answer += states[y - 1] - x
레이저의 x, y좌표를 입력받고, start, end값을 초기화한다. start, end는 각각 레이저의 영향을 받는 넴모의 최소y좌표, 최대 y좌표를 의미한다.
레이저의 영향을 받는 레이저 기준 오른쪽 넴모의 경우 states[y - 1] - x 로 구할 수 있다. 이는 레이저와 같은 y좌표에 있는 넴모의 개수이다.
문제는 레이저와 같은 x좌표에 있는 넴모의 개수를 구해야 한다. 즉 레이저 기준 위쪽에 있는 넴모의 개수를 구하는 것이 관건이다.
레이저의 위치를 기준으로 해당 위치보다 얼마나 높은 위치까지 넴모가 배치되어있는지 알기 어렵기 때문이다.
이 문제를 해결하기 위해 이분탐색을 사용하였다.
이분탐색에서 위치를 잡은 후 해당위치에 넴모가 있냐 없냐에 따라 판단하면 된다.
while (start < end) {
var mid = (start + end) / 2
if (states[mid] < x) {
end = mid
} else {
start = mid + 1
}
}
states[mid]값이 x보다 작다면 즉 해당 층수에 넴모가 레이저위에 없다면 end = mid로 할당한다.
만약 있다면 start = mid + 1로 할당한다.
이렇게 할당하면 최종적으로 start값에 가장 높은 층수가 기록된다.
answer += start - y + 1
if (x > maxNum!! || y > N || answer <= 0) {
println(0)
} else {
println(answer)
}
마지막으로 answer값에 start - y + 1 값을 할당하고 print해준다.
이 때 레이저의 좌표가 넴모가 위치한 좌표보다 위 또는 아래에 배치될 수 있으므로 그 경우를 예외처리해준다.
코드
import java.io.BufferedReader
import java.io.InputStreamReader
import kotlin.math.max
fun main() = with(BufferedReader(InputStreamReader(System.`in`))) {
val (N, Q) = readLine().split(" ").map { it.toInt() }
val states = readLine().split(" ").map { it.toInt() }
val maxNum = states.maxOrNull()
repeat(Q) {
var answer = 0
val(x, y) = readLine().split(" ").map { it.toInt() }
var start = 0
var end = N
answer += states[y - 1] - x
while (start < end) {
var mid = (start + end) / 2
if (states[mid] < x) {
end = mid
} else {
start = mid + 1
}
}
answer += start - y + 1
if (x > maxNum!! || y > N || answer <= 0) {
println(0)
} else {
println(answer)
}
}
}
'알고리즘' 카테고리의 다른 글
[프로그래머스 kotlin] 보석 쇼핑 (0) | 2024.05.19 |
---|---|
[프로그래머스 kotlin] 단어변환 (0) | 2024.05.18 |
[프로그래머스 kotlin] 네트워크 (0) | 2024.05.13 |
[kotlin 알고리즘] 정N각형의 삼각 분 (0) | 2024.05.11 |
[프로그래머스 kotlin] 괄호 회전하기 (0) | 2024.05.06 |