본문 바로가기

알고리즘 삽질장

[이코테] 다이나믹프로그래밍 - 1로 만들기

반응형

해당 포스팅의 문제의 출처는 나동빈님의 이것이 취업을 위한 코딩 테스트 교재를 공부하면서 풀이할 때 본인의 사고 과정 흐름과 문제 풀이를 기록하기 위함 입니다. 

 


문제설명

정수 X가 주어질 때 정수 X에 사용할 수 있는 연산은 다음과 같이 4가지 이다.

  1. X가 5로 나누어 떨어지면 5로 나눈다.
  2. X가 3으로 나누어 떨어지면 3으로 나눈다.
  3. X가 2로 나누어 떨어지면 2로 나눈다.
  4. X에서 1을 뺀다.

정수가 주어졌을 때, 연산 4개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오

입력조건

  • 첫째 줄에 정수 X가 주어진다.(1 <= X <= 30,000)

출력조건

  • 첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.

사고과정

  • DP 테이블을 활용한다는 점을 알았는데, 숫자가 증가할 때마다 1을 빼는 것이, 2로 나눈 것이 3으로 나눈 것이, 5으로 나눈 것이 각각의 단계를 거치고 난 후의 연산 최소 횟수가 무엇인지 비교를 해나가면서 구현했어야 함. 이를 구현하지 못함..
  • 점화식을 세워볼려고 나름 노력을 했지만.. 위 조건을 불만족하니 결과가 생각대로 안나옴..
  • 그리고 if 문을 elif로 바꾸게 되면 안된다. 왜냐하면 2,3,5의 공배수가 있기 때문이다!
  • DP 유형의 문제들 어려움 젠쟝..

풀이

import sys

x = int(input())
# DP 테이블
table = [0] * 30001

for i in range(2, x+1):
    # 1을 뺐을 경우
    table[i] = table[i-1] + 1
    # 2와 나누어 떨어질 경우 & 1을 뺏을 경우 비교
    if i % 2 == 0:
        table[i] = min(table[i], table[i//2] + 1)
    # 3과 나누어 떨어질 경우 & 직전 비교
    if i % 3 == 0:
        table[i] = min(table[i], table[i//3] + 1)
    # 5와 나누어 떨어질 경우 & 직전 비교
    if i % 5 == 0:
        table[i] = min(table[i], table[i//5] + 1)
print(table[x])
반응형