홍익이는 홍익대학교 프로그래밍 경진대회의 출제진이다. 홍익이는 새벽에 문제를 만들던 도중 뒤통수에 느껴지는 고통과 함께 정신을 잃었다.
홍익이는 좁은 방에서 눈을 떴다. 주변을 살펴보니 벽면에는 LED로 된 다섯 자리 십진수 N이, 그 옆에 T, G라는 알파벳과 함께 또 다른 정수 두 개가 쓰여 있었고, 벽 앞에는 버튼 A, B 두 개가 있었다.
버튼을 이리저리 눌러보던 똑똑한 홍익이는 어떻게 해야 방을 탈출할 수 있을지 금방 눈치챘다.
버튼과 수에 대해 홍익이가 알아낸 것은 다음과 같다.
또한 홍익이는 최대 T회 버튼을 누를 수 있고, 그 횟수 안에 LED로 표현된 N을 G와 같게 만들어야 탈출할 수 있다는 사실을 알아냈다.
똑똑한 홍익이는 이와중에 자존심이 발동해 버튼 누르는 횟수를 최소로 하여 방을 탈출하기로 했다.
홍익이의 방 탈출을 기원하며, 탈출에 필요한 최소의 버튼 횟수를 구하자.
첫 번째 줄에 N (0 ≤ N ≤ 99,999), T (1 ≤ T ≤ 99,999), G (0 ≤ G ≤ 99,999)가 공백 하나를 사이에 두고 주어진다.
각각 N은 LED로 표현된 수, T는 버튼을 누를 수 있는 최대 횟수, G는 탈출을 위해 똑같이 만들어야 하는 수를 뜻한다.
첫 번째 줄에 탈출에 필요한 최소의 버튼 횟수를 출력한다.
만약 탈출할 수 없다면 “ANG”을 따옴표 없이 출력한다.
1 7 10
7
버튼을 A A A B A A A 순서로 누르면
1 -> 2 -> 3 -> 4 -> 7 -> 8 -> 9 -> 10 순서로 숫자가 변한다.
7142 10 7569
3
7142 1 7569
ANG
63429 99999 231
ANG
옛날에 DSLR이라는 문제를 풀어봤었다. D인 경우 어떠한 연산을 하고 S, L, R에 따라 각기 다른 연산을 하면서 정답을 찾아내는 최소의 알파벳을 찾아내는 건데 이 문제도 비슷하다. A, B에 따른 각 다른 연산이 존재하고, 어떠한 답에 도달했을 때 최소 경로를 찾는 것이다. bfs를 이용하여 queue에 이런 각기 다른 경우들을 append 해주면서 답을 찾아내는 것인데, 유의해야 할 것은 visited 리스트를 이용하여 특정 수를 방문을 한다면 그 수는 다시 queue에 넣지 않게끔 방문 처리를 해줘야 한다. 안 그러면 같은 수들이 계속해서 들어가면서 같은 연산이 2 ^ n 번 만큼 반복이 되기 때문이다.
import sys
from collections import deque
N, T, G = map(int, sys.stdin.readline().split())
queue = deque()
queue.append((N, 0))
visit = [0] * 100000
if N == G:
print("0")
exit()
def bfs():
N_A = 0
N_B = 0
while queue:
flag = 0
N, count = queue.popleft()
if count == T:
continue
N_A = N + 1
if N_A == G:
print(count + 1)
flag = 1
break
if N_A < 100000 and visit[N_A] == 0:
visit[N_A] = 1
queue.append((N_A, count + 1))
if N != 0:
N_B = N * 2
if N_B > 99999:
continue
else:
list_N_B = list(str(N_B))
c = int(list_N_B[0])
c -= 1
list_N_B[0] = str(c)
a = 0
for i in range(len(list_N_B)):
a += int(list_N_B[i]) * (10 ** (len(list_N_B) - 1 - i))
# a = str(N_B)
# a = str(int(a[0]) - 1) + a[1:]
if int(a) == G:
print(count + 1)
flag = 1
break
if visit[int(a)] == 0:
queue.append((int(a), count + 1))
visit[int(a)] = 1
if flag == 0:
print("ANG")
bfs()