알고리즘/다이나믹프로그래밍(Dynamic Programming)

[백준-1003]-[다이나믹프로그래밍] - 피보나치 수열

팡스 2018. 11. 9. 13:06

문제링크 : https://www.acmicpc.net/problem/1003



이문제는 생각보다 쉽게 방법을 찾았다. 

다행이다.


문제에서 친절하게 C++ 피보나치 DP 소스를 제공해줬다. 하지만 이문제를 푸는데 대략적인 힌트만 줄 뿐 저 소스를 이용할 필요는 없다.


숫자 5까지의 피보나치를 계산해보면서 이 문제를 어떻게 풀어가야할지 방법을 파악해보자.


1
2
3
4
5
6
7
8
9
10
11
int fibonacci(int n) {
    if (n == 0) {
        printf("0");
        return 0;
    } else if (n == 1) {
        printf("1");
        return 1;
    } else {
        return fibonacci(n‐1) + fibonacci(n‐2);
    }
}
cs


숫자 0과 1이 들어오면 0, 1을 리턴한다고 한다.

그럼 저 둘은 기본값이겠구만 하는 똘똘한 생각을 해봤다. 



 

 fibonacci(n-1)

fibonacci(n-2) 

출력된 0의 횟수 

출력된 1의 횟수 

 0

-- 

-- 

 1

-- 

-- 

 2

 3

 4

 5



0부터 5까지의 피보나치를 돌면서 출력된 0과 1의 횟수를 뽑아 봤다. 저기서 공통점을 찾아볼 수가 있는데

기본값인 0과 1을 제외하고 2부터는 n-1의 0과 1의 횟수와 n-2의 0과 1의 횟수의 합이 n의 0과 1의 출력 횟수라는게 보인다.

나만의 점화식을 계산해본다면


각 숫자별 0과 1의 출력 횟수를 담고 있는 정수형 이차원 배열 cnt[N+1][2] 를 생성하고 재귀를 돌면서 계산 하면 된다. 

하지만 문제에서 최대값을 40으로 지정해줬기 떄문에 40까지 계산하고 입력받는 값들의 정보만 출력하면 된다.


cnt[n][0] = cnt[n-1][0] + cnt[n-2][0]

cnt[n][1] = cnt[n-1][1] + cnt[n-2][1]


아주 쉽게 점화식을 구했으니 이제 코딩을 해보자 잘 나오겠지


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
import java.util.Scanner;
 
public class E_1003 {
    
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
 
        int fibo = 40;
        int[][] cnt = new int[fibo+1][2];
        
        cnt[0][0= 1;
        cnt[1][1= 1;
        
        for(int i=2; i <=fibo; i++) {
            cnt[i][0= cnt[i-1][0+ cnt[i-2][0];
            cnt[i][1= cnt[i-1][1+ cnt[i-2][1];
        }
        
        
        int num = sc.nextInt();
        
        for(int i=0; i < num; i++) {
            int n = sc.nextInt();
            System.out.println(cnt[n][0+ " " + cnt[n][1]);
        }
    }
 
}
cs