알고리즘 연습/브루트 포스

[🥇5 / 백준 1107 / 파이썬] 리모컨

김세진 2021. 8. 11. 23:27
반응형

 

 

1107번: 리모컨

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

www.acmicpc.net

 

문제

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

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

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

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

입력

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

출력

첫째 줄에 채널 N으로 이동하기 위해 버튼을 최소 몇 번 눌러야 하는지를 출력한다.

 

예제 입력 1 

5457
3
6 7 8

예제 출력 1 

6

예제 입력 2 

100
5
0 1 2 3 4

예제 출력 2 

0

예제 입력 3 

500000
8
0 2 3 4 6 7 8 9

예제 출력 3 

11117

 

힌트

5455++ 또는 5459--

 

 

풀이

 

고장난 리모컨을 적절히 사용하여 해당 채널까지 갈 수 있는 최소한의 조작값을 구하는 문제이다.

 

처음엔 간단해보였지만 예외처리할게 생각보다 많아서 힘들었던 문제같다.

 

고려 사항이 꽤 있다. 나열해보자면

 

  • 현재 채널인 100에서 가는 것과 비교
  • 자릿수 2자리 까지 고려해야 하는 것 같다.
  • 성능 문제
  • 대소비교뿐 아니라 실제 조작과도 비교

마지막 항목을 예로 들자면,

0이 고장난 리모컨으로 채널 10을 가고 싶다고 가정하자.

만들 수 있는 채널들로 대소 비교를 하자면 가장 가까운 채널인 9와 11로 이동해서 +, - 버튼 조작을 할 수 있다.

허나, 채널 9는 버튼을 한 번 누르면 이동할 수 있지만 채널 11은 1을 두 번 눌러 이동해야 한다.

 

본인의 경우 대소리스트 비교 후 n과 같은 절댓값 차이를 가진 채널 리스트를 만들어두고

마지막에 문자열 길이 비교를 해주었다.

 

import sys
input = sys.stdin.readline

n,m = int(input()),int(input())
ln = len(str(n))
bt = [i for i in range(10)]
if m > 0:
    brk = list(map(int,input().split()))
    for i in brk:
        bt.remove(i)
    
    # 가고싶은 채널에 고장난 버튼의 숫자가 없을 때
    for i in brk:
        if str(n).count(str(i)):
            break
    else:
        print(min(ln,abs(100-n)))
        sys.exit()

# 고장난 버튼이 없을 때
if ln > 4 and m == 0:
    print(ln)
    sys.exit()
    
r = float('inf')
# 후보 숫자 리스트
cand = []
def bf(num, cnt):
    global r,n,cand
    if cnt+2 > ln and num != "":
        if abs(r-n) > abs(int(num)-n):
            r = int(num)
            cand = [r]
        elif abs(r-n) == abs(int(num)-n):
            cand.append(int(num))
        if cnt > ln:
            return
    
    for i in bt:
        bf(num+str(i),cnt+1)

bf("",0)
result = float('inf')
for i in cand:
    result = min(result, len(str(i))+abs(n-i))
print(min(result,abs(100-n)))
반응형