1. 점화식을 이용한 일반적인 방법


생각


단계1. 먼저 피보나치 수열은 앞에서도 이야기 했지만 f(n) = f(n-1) + f(n-2)로 정의된다. 

단계2. 이 식을 점화식으로 재귀함수를 만들 수있다.

함수 내용 

 - 함수 f는 n을 입력받아 n번째 피보나치수를 리턴하는 재귀함수이다.

 - n이 2 이하 라면 1을 리턴한다..

 - n이 3 이상 이라면 f(n-1) + f(n-2)를 리턴한다.


단계3. 리턴 받은 수를 2로 나눈 나머지가 0이라면 짝수 이므로 YES, 0이 아니라면 NO를 출력한다.


코드


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
30
31
32
33
#include <iostream>
 
// 함수 구현
// n번째 수의 피보나치 수열을 재귀적으로 반환
long long f(int n)
{
    // 기저사례 : n이 2 이하면 1반환
    if(n <= 2)
    {
        return 1;
    }
    // 점화식 f(N) = f(N-1) + f(N-2)
    return f(n-1+ f(n-2);
}
 
int main()
{
    // 테스트 케이스
    int testCase = 0;
    // 숫자 N
    int N = 0;
    scanf("%d", &testCase);
    
    while(testCase--){
        scanf("%d", &N);
        long long result = f(N);
        // 짝수면 YES
        if(result % 2 == 0)
            printf("YES\n");
        else
            printf("NO\n");
    }
}
cs

 

결과


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
10
10
NO
10
NO
10
NO
20
NO
30
YES
40
NO
50
NO
cs


답은 구했지만 위의 코드는 함수내에서 같은 함수를 2번 호출하는 재귀함수 이므로 2^n의 시간 복잡도를 가지며 매우 오랜시간이 걸린다. 




2. 캐시활용


생각


앞에서 [BOGGLEGAME_알고리즘_3] 에서 시간을 줄일때 사용했던 방법과 같은 아이디어로 시간을 절약 할 수있다.

단계1. 캐시를 저장할 수있는 배열을 정의하고 0으로 초기화한다.

단계2. 배열의  N번째 요소가 0이라는 것은 이전에 계산된적 없는 피보나치 수라는 것으로 계산하여   캐시배열에 저장한후 리턴한다.

단계3. 배열의 N번째 요소에 0이 아닌 값이 있다는 것은 한번 계산한 값이란 의미로 그 인덱스를 바로 참조하여 리턴한다.


코드


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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// FIBONACCI_2
 
#include <iostream>
 
// 캐시 저장 배열
long long g_CacheArr[1001= {0,};
 
// 함수 구현
// n번째 수의 피보나치 수열을 재귀적으로 반환
long long f(int n)
{
    // 기저사례 : n이 2 이하면 1반환
    if(n <= 2)
    {
        return 1;
    }
    
    // 캐시의 해당 요소가 아직 계산되지 않은 값이라면
    // 캐시 배열에 점화식으로 계산한 값 저장
    if(g_CacheArr[n] == 0)
        return g_CacheArr[n] = f(n-1+ f(n-2);
    else// 해당요소가 이미 계산된 값이라면 캐시값 리턴
        return g_CacheArr[n];
}
 
int main()
{
    // 테스트 케이스
    int testCase = 0;
    // 숫자 N
    int N = 0;
    scanf("%d", &testCase);
    
    while(testCase--){
        // 캐시배열 초기화
        memset(g_CacheArr, 0sizeof(g_CacheArr));
        scanf("%d", &N);
        long long result = f(N);
        // 짝수면 YES
        if(result % 2 == 0)
            printf("YES\n");
        else
            printf("NO\n");
    }
}
cs


결과


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
10
10
NO
20
NO
30
YES
40
NO
50
NO
60
YES
70
NO
80
NO
90
YES
1000
NO
cs

 


숫자가 작을때는 큰차이를 보이지 않지만 40이상만 넘어가더라도 매우 큰 차이를 확인 할 수있다. 

'All > Algorithm' 카테고리의 다른 글

JUMPGAME_알고리즘  (0) 2015.12.28
JUMPGAME_문제  (0) 2015.12.28
FIBONACCI_문제  (0) 2015.12.28
BOGGLEGAME_알고리즘_3  (0) 2015.12.28
BOGGLEGAME_알고리즘_2  (0) 2015.12.28

+ Recent posts