PS(Problem Solving)/BOJ

[백준/BOJ] 12851번: 숨바꼭질 2

JunsuKim 2022. 6. 23.
728x90

https://www.acmicpc.net/problem/12851

 

12851번: 숨바꼭질 2

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때

www.acmicpc.net

문제

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.

수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 그리고, 가장 빠른 시간으로 찾는 방법이 몇 가지 인지 구하는 프로그램을 작성하시오.

입력

첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.

출력

첫째 줄에 수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.

둘째 줄에는 가장 빠른 시간으로 수빈이가 동생을 찾는 방법의 수를 출력한다.

해설

bfs를 이용하여 해결하는 문제이다.https://jjunsu.tistory.com/197

 

[백준/BOJ] 1697번: 숨바꼭질

https://www.acmicpc.net/problem/1697 1697번: 숨바꼭질 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순..

jjunsu.tistory.com

위의 문제를 해결하고 온다면, 좀 더 수월할 것이다.위의 문제와 유사하므로 초반 설명은 건너뛰도록 하겠다.

 

위의 문제와는 달리 이 문제에서는

que에 값을 집어넣을 때 방문 여부 체크를 해주는 것이 아닌, que에서 값을 꺼낼 때 방문 여부를 체크해주어야 한다.

 

큐에 넣을 때 방문 여부 체크를 해준다면 그 다음에 같은 값이 나올 때가 처리되지 않기 때문이다.예를 들어보자.

목표값이 17일 때 16 + 1 = 17, 18 - 1 = 17이다.

이 때 16에서 16+1을 방문 여부 체크를 해주었다면, 18 - 1에서 방문을 못하게 된다.

따라서 먼저 다 넣은 후, que에서 꺼낼 때 방문 여부 체크를 해주는 것이다.

소스 코드

import java.util.*

private lateinit var visited: BooleanArray
private var ans = 0
private var cnt = 0

fun main() = with(System.`in`.bufferedReader()) {
    val (subinIdx, brotherIdx) = readLine().split(" ").map { it.toInt() }
    visited = BooleanArray(100001)

    bfs(subinIdx, brotherIdx)

    println(ans)
    println(cnt)
}

private fun bfs(subinIdx: Int, brotherIdx: Int) {
    val que: Queue<IntArray> = LinkedList()
    que.add(intArrayOf(subinIdx, 0))
    visited[subinIdx] = true

    while(!que.isEmpty()) {
        val idx = que.peek()[0]
        val moveCnt = que.peek()[1]
        que.poll()
        visited[idx] = true

        if(ans != 0 && idx == brotherIdx && ans == moveCnt) cnt++

        if(ans == 0 && idx == brotherIdx) {
            ans = moveCnt
            cnt++
        }

        if(idx - 1 in 0..100000 && !visited[idx - 1]) que.add(intArrayOf(idx -1, moveCnt + 1))
        if(idx + 1 in 0 .. 100000 && !visited[idx + 1]) que.add(intArrayOf(idx + 1, moveCnt + 1))
        if(idx * 2 in 0 .. 100000 && !visited[idx * 2]) que.add(intArrayOf(idx * 2, moveCnt + 1))
    }
}
728x90

댓글