# 문제
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 그리고, 가장 빠른 시간으로 찾는 방법이 몇 가지 인지 구하는 프로그램을 작성하시오.
# 입력
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
# 출력
첫째 줄에 수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
둘째 줄에는 가장 빠른 시간으로 수빈이가 동생을 찾는 방법의 수를 출력한다.
# 풀이
- trace 기법 (
prev[next] = current
) 기억하기 - 최대범위가 10만이 아닌 20만이어야 함. 수빈이의 첫 좌표가 10만이지 그 이후로 움직이는 좌표는 범위가 특정되지 않는다.
import Foundation
struct Queue<T> {
var head = 0
var array: [T?] = []
var count: Int {
return array.count - head
}
var isEmpty: Bool {
return count == 0
}
mutating func enqueue(_ element: T) {
array.append(element)
}
mutating func dequeue() -> T? {
guard head < array.count,
let element = array[head] else { return nil }
array[head] = nil
head += 1
let percentage = Double(head) / Double(array.count)
if percentage > 0.25 && array.count > 50 {
array.removeFirst(head)
head = 0
}
return element
}
var front: T? {
if isEmpty {
return nil
} else {
return array[head]
}
}
}
let nk = readLine()!.split(separator: " ").map { Int($0)! }; let n = nk[0]; let k = nk[1]
var visited: [Int] = .init(repeating: 0, count: 200004)
var prev: [Int] = .init(repeating: 0, count: 200004)
var ret = 0
var q = Queue<Int>()
q.enqueue(n)
visited[n] = 1
while(!q.isEmpty) {
guard let current = q.front else { break }
_ = q.dequeue()
if current == k {
ret = visited[k]
break
}
for next in [current + 1, current - 1, current * 2] {
if next < 0 || next >= 200004 || visited[next] != 0 {
continue
}
visited[next] = visited[current] + 1
q.enqueue(next)
prev[next] = current
}
}
print(ret - 1)
var next = k
var lists: [Int] = []
while(next != n) {
lists.append(next)
next = prev[next]
}
lists.append(n)
lists.reverse()
lists.forEach { print($0, terminator: " " )}