본문 바로가기

IT/Python

[백준] 12851번 숨바꼭질 2 [Python]

728x90

 

수빈$($=N$)$이가 동생 $($=K$)$ 을 찾는 데 걸리는 최소 시간을 구하는 문제

+1, -1, x2 : 1초 소요

 

추가로 최소 소요 시간이 걸리는 방법의 수도 구해야한다.

 

더보기

문제

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

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

입력

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

출력

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

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

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

 

N -> K는 2배 연산을 항상 할 수 있는데,

K -> N은 나누기 2 연산을 짝수 일 때만 할 수 있어서

경우의 수를 줄일 수 있다.

 

K -> N 과정으로 경우의 수를 구하는 코드를 작성했다.

N이 0인 경우는 +1 연산 후  마지막 소요시간에 1초를 추가한다.

 

+1, -1, /2 연산을 하면서 1초를 더하고, 값이 N이 될 때까지 탐색을 계속한다.

N에 처음 도달하면 그 소요 시간이 최소 시간이다.

그 이후로 N에 다시 도착하는 다른 경우가 있을 때,

소요 시간이 더 크면 더 이상 최소 소요 시간으로 도착할 수 있는 방법이 없다.

소요 시간이 같으면 방법의 수에 +1을 해준다.

 

import sys
input = sys.stdin.readline

def bfs(N, K):
    stack = [(K, 0)]
    M = 10**5+1
    v = [False]*(M)
    s, c = M, 0
    flag = 0

    if not N:
        N += 1
        flag = 1

    while stack:
        k, t = stack.pop(0)
        v[k] = True

        if k == N:
            if t <= s:
                s = t
                c += 1
            elif t > s:
                return "\n".join(map(str, (s+flag, c)))
            
        for i in (k-1, k+1, [k//2, -1][k%2]): 
            if 0 <= i < M and not v[i]:
                stack.append((i, t+1))
    return "\n".join(map(str, (s+flag, c)))

if __name__ == "__main__":
    N, K = map(int, input().split())
    print(bfs(N, K))

 

더보기

예제 입력 1 

5 17

예제 출력 1 

4
2