https://www.acmicpc.net/problem/16397
문제
홍익이는 홍익대학교 프로그래밍 경진대회의 출제진이다. 홍익이는 새벽에 문제를 만들던 도중 뒤통수에 느껴지는 고통과 함께 정신을 잃었다.
홍익이는 좁은 방에서 눈을 떴다. 주변을 살펴보니 벽면에는 LED로 된 다섯 자리 십진수 N이, 그 옆에 T, G라는 알파벳과 함께 또 다른 정수 두 개가 쓰여 있었고, 벽 앞에는 버튼 A, B 두 개가 있었다.
버튼을 이리저리 눌러보던 똑똑한 홍익이는 어떻게 해야 방을 탈출할 수 있을지 금방 눈치챘다.
버튼과 수에 대해 홍익이가 알아낸 것은 다음과 같다.
- 버튼 A를 누르면 N이 1 증가한다.
- 버튼 B를 누르면 N에 2가 곱해진 뒤, 0이 아닌 가장 높은 자릿수의 숫자가 1 줄어든다. 예를 들어 123→146으로, 5→0으로, 3→5로 변한다. 단, N이 0이면 버튼 B를 눌러도 수가 변하지 않는다.
- LED가 다섯 자리까지밖에 없기 때문에 N이 99,999를 넘어가는 순간 탈출에 실패하게 된다.
- 버튼 B를 눌러 N에 2를 곱한 순간 수가 99,999를 넘어간다면, 높은 자릿수의 수를 1 낮췄을때 99,999를 넘지 않는다고 해도 탈출에 실패하게 된다.
또한 홍익이는 최대 T회 버튼을 누를 수 있고, 그 횟수 안에 LED로 표현된 N을 G와 같게 만들어야 탈출할 수 있다는 사실을 알아냈다.
똑똑한 홍익이는 이와중에 자존심이 발동해 버튼 누르는 횟수를 최소로 하여 방을 탈출하기로 했다.
홍익이의 방 탈출을 기원하며, 탈출에 필요한 최소의 버튼 횟수를 구하자.
입력
첫 번째 줄에 N (0 ≤ N ≤ 99,999), T (1 ≤ T ≤ 99,999), G (0 ≤ G ≤ 99,999)가 공백 하나를 사이에 두고 주어진다.
각각 N은 LED로 표현된 수, T는 버튼을 누를 수 있는 최대 횟수, G는 탈출을 위해 똑같이 만들어야 하는 수를 뜻한다.
출력
첫 번째 줄에 탈출에 필요한 최소의 버튼 횟수를 출력한다.
만약 탈출할 수 없다면 “ANG”을 따옴표 없이 출력한다.
풀이
재귀로 A 연산, B 연산을 하면서 탐색하기엔 T의 수가 매우커서 시간초과가 발생한다.
그런데 최소의 버튼횟수를 출력하는 것이기 때문에, 어떤 특정수에 도달했는데, 그 수가 이미 계산된적이 있다면 더이상 진행할 필요가 없다. 왜냐하면 이미 이전 계산횟수보다 많아지기 때문에 최소라는 조건에 어긋난다.
따라서 방문을 체크하는 BFS로 문제를 해결한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
# [파이썬 | BOJ | 16397] 탈출(홍익대 프로그래밍 대회)
import sys
from math import log10
from collections import deque
read = sys.stdin.readline
def calA(n):
return n+1
def calB(n):
if n == 0:
return 0
n *= 2
if n > 99999:
return -1
d = int(log10(n))
return n - 10 ** d
def solve():
global minAns
q = deque()
q.append([N, 0])
check[N] =1
while q:
num, cnt = q.popleft()
#print(num, cnt, G)
if cnt > T:
break
if num == G:
if minAns > cnt:
minAns = cnt
#print(num, cnt, G)
continue
nextNum = calA(num)
if 0 <= nextNum <= 99999:
if check[nextNum] == 0:
q.append([nextNum, cnt+1])
check[nextNum] = 1
nextNum = calB(num)
if 0 <= nextNum <= 99999:
if check[nextNum] == 0:
q.append([nextNum, cnt+1])
check[nextNum] = 1
check = [0 for _ in range(100000)]
N, T, G = map(int, read().split())
minAns = T+1
solve()
print(minAns if minAns != T+1 else "ANG")
|
cs |
'알고리즘' 카테고리의 다른 글
[파이썬 | BOJ | 17873] 새로운 게임2 (0) | 2020.05.01 |
---|---|
[파이썬 | BOJ | 17281] ⚾ (0) | 2020.05.01 |
[파이썬 | BOJ | 1620] 나는야 포켓몬 마스터 이다솜 (0) | 2020.04.30 |
[파이썬 | BOJ | 1120] 문자열 (0) | 2020.04.30 |
[파이썬 | BOJ | 17140] 이차원 배열과 연산 (0) | 2020.04.29 |