[알고리즘] Dynamic Programming(동적 계획법)

2023. 3. 17. 18:21·Algorithm/KBro Study

1. DP란?

DP(Dynamic Programming)은 하나의 큰 문제를 여러 개의 작은 문제로 나누어서 그 결과를 저장하여 다시 큰 문제를 해결할 때 사용하는 것으로, 이미 했던 연산이 반복되는 결점을 보완하기 위해서 고안되었다.

 

피보나치 수열에서 사용되는 일반적인 재귀 방식도 DP와 매우 유사하지만, 일반적인 재귀 방식은 동일한 작은 문제들이 여러 번 반복되어 비효율적인 계산이 될 수도 있다는 것이다.

 

Dynamic Programming 문제를 풀기 위한 방법에는 Top-Down과 Bottop-Up 방식이 있는데, 아래에서 알아보겠다. 


2. Dynamic Programming 구현

2-1 Top-Down 방식

Top-Down 방식이란 재귀 함수로 다이나믹 프로그래밍을 구현하는 방식이며,

말 그대로 문제 풀이가 위에서 아래로 진행된다.

예를 들어 n에 6을 대입하면 fibonacci(6)부터 차례대로 return fibonacci(5) + fibonacci(4) ... 으로 1과 0까지 도달하는 방식이다.

=> 가장 큰 문제를 방문 후 작은 문제를 호출 하여 답을 찾는 방식

 

피보나치 수열을 일반적인 재귀 함수로 구현하면 아래와 같다.(시간복잡도 O(N^2))

int fibonacci(int n)
{
  if ( n <= 1 ) {
    return n;
  }
   
  return fibonacci(n-1) + fibonacci(n-2);
}

 

자 그러면 위와 같은 일반적인 재귀함수를 DP의 Top-Down 방식으로 변경해보자.

일반적으로 재귀를 사용하는 구조는 같지만, 부분 문제에서 구한 값을 기억(Memoization)하면서 다음 재귀에서 재활용하는 과정을 추가해주면 된다.

 

public class Main {
	// Memoization을 적용할 배열.
	static long[] dp;

	public static void main(String[] args) {
	
		int n = n번째 피보나치 수를 구하기 위한 숫자;
		dp = new long[n + 1];

		// n번째 피보나치 수를 구하고 출력
		System.out.println(Fibonacci(n));
	}


    static long Fibonacci(int n) {
        // 기저 조건(피보나치 수열의 초항).
        if (n == 1 || n == 2) {
            return dp[n] = 1;
        }
        // 만일, 저장된 값이 존재하는 경우 기억된 값을 바로 넘겨준다.
        if (dp[n] != 0) {
            return dp[n];
        }
        // 그렇지 않은 경우, 기저 조건까지 내려가서 구해진 값을 저장하면서 재귀를 전이한다.
        else {
            return dp[n] = Fibonacci(n - 1) + Fibonacci(n - 2);
        }
	}
}

   

이렇게 부분 문제에서 해결한 값을 저장(Memoization)하면서 문제를 해결하는 경우엔 불필요한 계산 과정을 줄여주기 때문에 시간복잡도 O(N)의 엄청난 속도 향상을 보일 수 있다.


2-2 Bottom-Up 방식

Bottom-Up방식이란, 단순히 반복문으로 다이나믹 프로그래밍을 구현하는 방식이고, DP테이블을 활용한다.

Top-Down방식과 동일한 원리이지만, 단순히 반복문을 이용하는 방식이다.

=> 다이나믹 프로그래밍의 전형적인 형태

 

마찬가지로, 피보나치 수열을 구하는 함수를 DP 테이블을 활용한 Bottom-UP방식으로 구현하면 아래와 같다.

public class Main {
	// DP 테이블 생성
	static long[] dp;

	public static void main(String[] args) {
	
		int n = n번째 피보나치 수를 구하기 위한 숫자;
		dp = new long[n + 1];

		// n번째 피보나치 수를 구하고 출력
		System.out.println(Fibonacci(n));
	}


    static long Fibonacci(int n) {
        // 기저 조건(피보나치 수열의 초항).
        dp[0] = 0;
        dp[1] = 1;
        
        # 피보나치 함수(Fibonacci Function) 반복문으로 구현(Bottom-Up 방식)
        for(int i = 2; i < n+1; i++) {
            dp[i] = dp[i-1] + dp[i-2]; 	
        }
        return dp[n];
    }
}

 

이처럼, Bottom-Up 방식은 작은 문제부터 차례로 답을 구해나가는 방식이다.

 

 

📗참고사이트

동적 프로그래밍 DP(Dynamic Programming - top- down, bottom-up)

[Algorithm] Top-Down, Bottom-Up 이란?

Top-down(탑다운) vs Bottom-up(바텀업)

[Java]동적 계획법(Dynamic Programming)

알고리즘 - Dynamic Programming(동적 계획법)

'Algorithm > KBro Study' 카테고리의 다른 글

[알고리즘] 투포인터(Two Pointer) 알고리즘  (0) 2023.04.20
[알고리즘] LCS(최장 공통 부분 수열) & LIS(가장 긴 증가하는 부분 수열)  (0) 2023.03.27
[알고리즘] 벨만포드 알고리즘 (Bellman-Ford)  (0) 2023.03.02
[알고리즘] 그리디 - 최소 스패닝 트리(Minimum Spanning Tree)  (0) 2023.02.19
[자료구조] 그래프(Graph) + 구현하기(Java의 인접행렬과 인접리스트)  (0) 2023.01.17
'Algorithm/KBro Study' 카테고리의 다른 글
  • [알고리즘] 투포인터(Two Pointer) 알고리즘
  • [알고리즘] LCS(최장 공통 부분 수열) & LIS(가장 긴 증가하는 부분 수열)
  • [알고리즘] 벨만포드 알고리즘 (Bellman-Ford)
  • [알고리즘] 그리디 - 최소 스패닝 트리(Minimum Spanning Tree)
Ohde
Ohde
블로그 이사했습니다! https://velog.io/@pigonhair/posts
  • Ohde
    Ohde's Blog
    Ohde
  • 전체
    오늘
    어제
    • 전체 (83)
      • Languages | Frameworks (41)
        • Java (10)
        • Spring (23)
        • Docker (8)
      • Git | Github (1)
      • DBMS (4)
        • SQL (4)
      • DevOps | Server (3)
      • OS (6)
        • Linux (6)
      • Algorithm (26)
        • Theory (1)
        • Data Structure (7)
        • BaekJoon (5)
        • Programmers (1)
        • KBro Study (12)
  • 블로그 메뉴

    • Github
    • BaekJoon
    • solved class
    • 방명록
  • 인기 글

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Ohde
[알고리즘] Dynamic Programming(동적 계획법)
상단으로

티스토리툴바