알고리즘/동적프로그래밍

1463. 1로 만들기

위대한루루 2019. 11. 19. 16:49

어렵다.

동적 프로그래밍은 점화식을 세우면 풀 수 있다고 했는데,

점화식은 세웠는데 그걸로 어떻게 구현해야할지 재귀에서 한참 헤맸다.

처음이라 그런지, 피보나치만 생각하고 Top-down만 생각했던 게 실수였던 것 같다.

또, 점화식이 D(n) = min(D(n/3), D(n/2), D(n-1)) + 1 이런 식으로 나오다보니 자연스럽게 탑다운만 생각했다.

 

사실, 탑다운도 가능하고 바텀업도 가능하다.

하지만 실행 시 탑다운 방식은 큰 수를 넣으면 재귀가 너무 깊다고 하면서 오류가 뜬다.

 

 

 

Top-Down (큰 수 오류)

enter = int(input())
m = [-1 for i in range(enter + 1)]  # memoization

def dp(n):
    if n == 1:
        return 0
    if n == 2 or n == 3:
        return 1
    if m[n] != -1:
        return m[n]
    temp1 = dp(n-1) + 1  # -1 했을 때 최소 연산
    temp2 = temp1  # 0으로 하면 안되서 temp1과 같게 해 줌
    temp3 = temp1
    if n % 2 == 0:
        temp2 = dp(n//2) + 1
    if n % 3 == 0:ㅁ
        temp3 = dp(n//3) + 1
    m[n] = min([temp1, temp2, temp3])
    return m[n]

print(dp(enter))

 

 

 

Bottom-Up

n = int(input())
m = []  # 미리 초기화를 하면 밑부분 m[0]~m[3]을 초기화해주는 부분에서 out of index 날 수 있다

m.append(0)
m.append(0)
m.append(1)
m.append(1)

for i in range(4, n+1):
    m.append(m[i-1] + 1);
    if(i % 2 == 0):
        m[i] = min(m[i], m[i//2] + 1) 
    if(i % 3 == 0):
        m[i] = min(m[i], m[i//3] + 1) 

print(m[n])

 

이 문제에서 생각해내지 못한 것은 10번째 줄이다.

-1 하는 것을 기본으로 놓고,

그 이후에 2나 3으로도 계산해보면서 무엇이 최솟값인지 비교해보는 방식으로 푸는 것이었다.