[BOJ] 리모컨 (no.1107)

숑숑·2021년 1월 12일
0

알고리즘

목록 보기
19/122

문제

수빈이는 TV를 보고 있다. 수빈이는 채널을 돌리려고 했지만, 버튼을 너무 세게 누르는 바람에, 일부 숫자 버튼이 고장났다.

리모컨에는 버튼이 0부터 9까지 숫자, +와 -가 있다. +를 누르면 현재 보고있는 채널에서 +1된 채널로 이동하고, -를 누르면 -1된 채널로 이동한다. 채널 0에서 -를 누른 경우에는 채널이 변하지 않고, 채널은 무한대 만큼 있다.

수빈이가 지금 이동하려고 하는 채널은 N이다. 어떤 버튼이 고장났는지 주어졌을 때, 채널 N으로 이동하기 위해서 버튼을 최소 몇 번 눌러야하는지 구하는 프로그램을 작성하시오.

수빈이가 지금 보고 있는 채널은 100번이다.

입력

첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼이 주어지며, 같은 버튼이 여러 번 주어지는 경우는 없다.


반례 진짜 많다. 어떻게든 최소 반복만으로 해결해보려고 이렇게 짠건데
순수 브루트포스로 하는게 나았으려나 싶기도 하다. 반례 다 잡는데 오래 걸렸다...

🤔 생각

  • 경우를 나누어서 생각했다.
  • 누를 수 있는 채널 중, 이동하려는 채널에서 가장 가까운 채널로 이동하고
  • +,- 버튼을 누르며 타겟 채널로 이동하면 최소가 되겠다.

특이 케이스

  1. 타겟 채널이 98~102 인 경우 (갭이 2 이하인 경우)
    • 방향키 버튼만 눌러 이동하는게 더 빠르니 따로 처리해준다.
  2. 고장난 버튼이 없는 경우
    • 1의 경우에 해당되지 않는다면 타겟 채널의 자릿수만큼을 출력한다.
  3. 전부 고장난 경우
    • 방향키만 사용할 수 있으므로, abs(타겟 채널 - 현재 채널)만 출력한다.
  4. 가장 가까운 채널 입력 후 이동보다 순수 방향키만으로 이동한게 더 가까운 경우
    • 마지막에 min() 함수로 묶어서 더 작은 쪽을 출력하게 한다.

📌 내 풀이

import sys
input = sys.stdin.readline
#print = sys.stdout.write

N = int(input())
M = int(input())

gap = abs(N-100)
if gap <= 2:
    if M != 0: input()
    print(gap)
    sys.exit(0)

if not M:
    print(len(str(N)))
    sys.exit(0)

buttons = set(map(str, range(0,10))) - set(input().split())   
if not buttons:
    print(gap)
    sys.exit(0)

up, down = 1000000, 1000000
for num in range(N, 1000001):
    for i in str(num):
        if i not in buttons: break
    else:
        up = num
        break
    
for num in range(N, -1, -1):
    for i in str(num):
        if i not in buttons: break
    else: 
        down = num
        break

closest = up if abs(up-N) < abs(down-N) else down
print(min(len(str(closest)) + abs(closest-N), gap))

✔ 배운 점

  • 반례를 하나하나 다 생각해서 짜기 보다는
  • 브루트포스 구조를 빨리 생각해서 돌리는게 나을 수도 있다. (효율성은 좀 버리겠지만..)
profile
툴 만들기 좋아하는 삽질 전문(...) 주니어 백엔드 개발자입니다.

0개의 댓글