Post

DP

목차

1
2
3
4
5
6
7
8
9
1. dp(동적 계획법)의 특징

2. 팩토리얼을 통한 재귀함수 표현

3. 피보나치수열의 형태 및 한계

4. dp(동적계획법)을 활용한 한계 극복
1) Memoization (Top-Down, 하향식)
2) Tabulation (Bottom-up, 상향식)

1. dp(동적 계획법)의 특징

  • 큰 문제를 작게 나누고, 같은 문제라면 한번만 풂
  • 한번 계산한 문제는 다시 계산 안하는 알고리즘

2. 팩토리얼을 통한 재귀함수 표현

잠깐! 재귀함수란 무엇인가? —> 함수 안의 자신의 함수를 다시 호출

(자신의 로직을 반복하다 일정 조건이 만족되면 함수를 이탈하여 결과를 도출)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def factorial(x):
  if x > 1:
    return x * factorial(x-1)
  else:
    return x

for x in range(5+1):        # 0 부터 5까지 반복
  print(factorial(x))

# 결과
# 0
# 1
# 2
# 6
# 24
# 120

3. 피보나치수열의 형태 및 한계

  • dp를 재귀 함수 중 하나인 피보나치수열에 적용 가능하다.
  • 기본형태는 f(x) = f(x-1) + f(x-2)
1
2
3
4
5
6
7
def fibonacci(x):
  if x == 0:
    return 0
  elif x == 1 or x ==2:
    return 1
  else:
    return fibonacci(x-1) + fibonacci(x-2)

Desktop View

x = 5 일 때

Desktop View

★위의 도식화는 총 x=5 대입 후, 15회 계산한 것

  • 수기로 작성한 도식화를 보면 이미 한번 계산한 값도 계속 호출할 때마다 계산했다.
  • 혹시 x가 크다면 기하급수적으로 계산과정이 길어진다.

4. dp(동적계획법)을 활용한 한계 극복

Desktop View

1). Memoization (Top-Down, 하향식)

하향식(Top-Down) 경우 하위 문제에 대하여 정답을 계산했는지 확인해가며 문제를 자연스럽게 풀어나가는 방법이다. 흔히 이를 Memoization이라고 부른다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# DP, Memoization

dp_Memo=[0]*11
dp_Memo[0]=1
dp_Memo[1]=1

def fib_Memo(n):
    
    #한번도 계산한 적이 없는 경우
    
    if dp_Memo[n]==0: #dp list에 계산한적이 없는경우 0으로 저장되어 있음
        dp_Memo[n] = fib(n-1)+fib(n-2) #재귀로 계산하여 리스트에 값 추가
    
    # 새롭게 추가 값 혹은 저장된 값 반환
    
    return dp_Memo[n]

# 피보나치 수열 항 리스트 전체 출력
for i in range(11):
    fib_Memo(i)

print(dp_Memo)

fib_Memo(10)

"""
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
output: 89
"""

2). Tabulation (Bottom-up, 상향식)

상향식(Bottom-Up)은 더 작은 하위 문제부터 살펴본 다음 작은 문제의 정답을 이용하여 큰 문제의 정답을 풀어나가는 방법이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 풀이 1.
def fib_Tab1(n):
    
    dp_Tab=[0]*(n+1)
    dp_Tab[0],dp_Tab[1]= 1,1
    
    # 작은 값(소문제)부터 직접 계산하며 진행
    
    # 2항 ~ n항 까지 피보나치 수열항 계산 (0,1 항 = 1)
    for i in range(2,n+1):        
        dp_Tab[i]=dp_Tab[i-1]+dp_Tab[i-2]
    
    print(dp_Tab) # 피보나치 수열 항 리스트 전체 출력
    
    return dp_Tab[n]

fib_Tab(10)

"""
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
output: 89
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 풀이 2.

def fib_Tab2(n):
	p=[1,1]
	for i in range(2,n+1): # n번째 까지 피보나치 수열 나열
												 # 여기서 range 범위는 ***2 <= i < n***
		p.append(p[-1]+p[-2]) # 마지막 2 요소의 합을 리스트에 추가
		print(p)
	return(p[-1]) #피보나치 n번째 값 Return

fib_Tab2(10)
"""
output: 89
"""




참고

https://velog.io/@seulki971227/프로그래머스-Lv.3-정수-삼각형-Python

https://velog.io/@bonjaski0989/동적계획법Dynamic-Programming-정리글Python

https://data-marketing-bk.tistory.com/27

This post is licensed under CC BY 4.0 by the author.
3D GIF