#1 알고리즘
N = 2 이상인 큰 문제를, N = 1이 될 때까지 작은 문제로 쪼개어 푼다. 그러려면 f(큰 문제) = 작은 문제인 f(x)를 알아야 한다. 규칙을 수식으로 표현해내어야 한다. '바둑판'의 영역을 4개로 나누어보자. 그리고 각 영역의 맨 ↖에 있는, 영역의 첫 원소들을 비교한다.
영역 m ~ 영역 (m + 1) 간 첫 원소의 값 차이는 N = 1일 때 1, N = 2일 때 4, N = 3일 때 16, N = 4일 때 64 ... 다. 이를 일반화하면 영역 간 첫 원소의 값 차이(interAreaFirstElementDifference)는 2(N-1)*2이다.
즉 어떤 영역 m에 있어, 칸마다 써진 수는 (영역 0의 수) + m * 2(N-1)*2다. 보라색 글씨 부분을 축적된(accumulated) 값이라고 부르기로 한다.
이제 f(큰 문제) = 작은 문제인 f(x)를 도출할 수 있다. 이 때, 큰 문제에서의 r행 c열은 작은 문제에서의 r행 c열과 항상 같지 않으므로, f(x)에 r값과 c값을 적절히 조절하는 로직도 추가한다. '바둑판'의 한 변의 길이는 2N이므로, 그 절반인 2N / 2 = 2N-1만큼(sideLengthHalf) r값이나 c값을 적절히 조정하면 된다.
#2 코드 - 코틀린
import kotlin.math.pow
/*
area 0 | area 1
---------------
area 2 | area 3
*/
fun main() {
val input = readln().split(" ")
val n = input[0].toInt()
val r = input[1].toInt() // rowIndex
val c = input[2].toInt() // columnIndex
println(calculateVisitIndex(n, r, c, 0))
}
fun calculateVisitIndex(nArgs: Int, rArgs: Int, cArgs: Int, accumulatedArgs: Int): Int {
if (nArgs == 1) {
return accumulatedArgs + (rArgs * 2) + cArgs
}
var r = rArgs
var c = cArgs
var accumulated = accumulatedArgs
val interAreaFirstElementDifference = exponentiation(2, (nArgs - 1) * 2)
val sideLengthHalf = exponentiation(2, nArgs - 1)
when (calculateTargetArea(nArgs, rArgs, cArgs)) {
0 -> { // 아무것도 안 함
}
1 -> {
c -= sideLengthHalf
accumulated += interAreaFirstElementDifference * 1
}
2 -> {
r -= sideLengthHalf
accumulated += interAreaFirstElementDifference * 2
}
3 -> {
r -= sideLengthHalf
c -= sideLengthHalf
accumulated += interAreaFirstElementDifference * 3
}
}
return calculateVisitIndex(nArgs - 1, r, c, accumulated)
}
fun exponentiation(base: Int, exponent: Int): Int { // 거듭제곱
return base.toDouble().pow(exponent.toDouble()).toInt()
}
fun calculateTargetArea(n: Int, r: Int, c: Int): Int {
if (r < exponentiation(2, n - 1)) {
if (c < exponentiation(2, n - 1)) { // area 0
return 0
} else { // area 1
return 1
}
} else {
if (c < exponentiation(2, n - 1)) { // area 2
return 2
} else { // area 3
return 3
}
}
}
'문제 풀이 > 기타' 카테고리의 다른 글
[백준] 2630 (색종이 만들기) (0) | 2024.03.04 |
---|---|
[백준] 21736 (헌내기는 친구가 필요해) (0) | 2024.03.02 |
[백준] 10816 (숫자 카드 2) (0) | 2024.02.06 |
[백준] 1929 (소수 구하기) (0) | 2024.02.05 |
[백준] 18110 (solved.ac) (0) | 2024.01.08 |