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

 

1107번: 리모컨

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

www.acmicpc.net

 

  • 채널이 50만번까지 있지만, 채널 버튼을 누르는건 500000을 누르더라도 5, 0, 0, 0, 0, 0 6번밖에 되지 않기 때문에 브루트포스를 사용해 구할 수 있음을 캐치해야했던 문제
  • 처음엔 누를 수 있는 채널들 중 가장 주어진 채널 값과 가장 가까운 값을 한번에 찾는 방법을 생각해 그리디 알고리즘으로 풀어보려고 했지만, 계속 반례가 등장하는 바람에 포기할 수 밖에 없었다.

** 주요 포인트 **

  • 그리디 알고리즘으로 풀 경우 자릿수가 변하는 경우도 체크를 해주어야 했고, 낮은 값에서 올라가는게 유리한지, 높은 값에서 내려가는게 유리한지도 체크를 해주어야 했다.
  • 자릿수도 자릿수를 늘린 뒤 줄여 가는 방법 ex) 999로 가기 위해 1000에서 내려가기, 자릿수를 줄인 뒤 늘려가는 방법 ex) 9에서 11로 가기, 같은 자릿수더라도 작은 숫자에서 올리기 ex) 8000으로 가기위해 9221 을 눌러야 하는 경우가 있고 7779를 눌러야 하는 경우가 있다.
  • 로직이 잘못된 걸 수도 있지만 이 경우들을 고려해주어도 계속 놓치는 반레들이 생겨났고, 결국 브루트포스로 문제를 풀 수 밖에 없었다
  • 채널 100번에서 시작하므로 버튼을 가장 많이 누르게 되는 경우(모든 숫자가 고장났을 경우) 채널 최댓값인 50만까지 가는데 49900이 들게 되지만 50만에서 시작할 경우 0까지 탐색을 해주기 위해서 그냥 반복을 50만번 수행하도록 했다.

 

코드 공유

 

더보기
S = input()
N = int(input())
ans = -1
min_ans = 9999999
if N != 0 :
    n_lst = list(map(int, input().split()))
    move = 0
    for move in range(500000) :
        plus_number = int(S) + move #채널 하나를 올려보고 그곳에서 접근할 수 있는지 체크
        minus_number = int(S) - move #채널 하나를 내려보고 그곳에서 접근할 수 있는지 체크
        for i in str(plus_number): # 해당 채널에 이동이 가능하다면 더 move할 필요없이 break
            if int(i) in n_lst :
                break
        else :
            plus_number = abs(int(S) - plus_number) + len(str(plus_number))
            min_ans = min(min_ans, plus_number)

        if minus_number >= 0 :
            for i in str(minus_number):
                if int(i) in n_lst:
                    break
            else :
                minus_number = abs(int(S) - minus_number) + len(str(minus_number))
                min_ans = min(min_ans, minus_number)

        move +=1

else :
    min_ans = len(S)
print(min(abs(100-int(S)), min_ans)) # 100에서 이동하는 것과 구해놓은 채널에서 이동하는 것중 작은 값 출력

'알고리즘 스터디' 카테고리의 다른 글

백준 22856. 트리 순회 - 파이썬  (0) 2023.03.01

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

 

22856번: 트리 순회

노드가 $N$개인 이진 트리가 있다. 트리를 중위 순회와 유사하게 순회하려고 한다. 이를 유사 중위 순회라고 하자. 순회의 시작은 트리의 루트이고 순회의 끝은 중위 순회할 때 마지막 노드이다.

www.acmicpc.net

  • 중위순회를 하면서 거쳐갔던 노드들을 카운트하는 문제
  • 재귀연산을 통해 전위, 중위, 후위 순회를 표현하는 법은 배웠지만, 그 순회를 이용해서 다른 문제를 푸는 문제는 처음이었더라 시간이 좀 걸렸던 문제
  • 중위 순회에서 우리가 알 수 있는건, 트리의 가장 왼쪽 노드와 그 노드의 부모노드 그리고 리프노드 값이다!
  • 유사 중위 순회에서 대부분의 값들은 다시 자기자신으로 돌아오지만, 리프노드를 호출한 함수는 돌아오지 않는다는 걸 체크

핵심코드

 

 

 

더보기
def inorder(t):
    global cnt, ans
    if t :
        left = inorder(c1[t])
        if left :
            cnt += 2
        if t == leaf_node :
            return -1
        right = inorder(c2[t])
        if right == -1 :
             cnt += 1
             return -1
        elif right :
            cnt += 2

        return t
    else :
        return 0

'알고리즘 스터디' 카테고리의 다른 글

백준 1107. 리모컨 - Python  (0) 2023.03.05

+ Recent posts