개발하고/코딩테스트

[백준] 1003번 피보나치 함수

씩씩환 2021. 8. 2. 16:31

https://www.acmicpc.net/problem/1003

 

1003번: 피보나치 함수

각 테스트 케이스마다 0이 출력되는 횟수와 1이 출력되는 횟수를 공백으로 구분해서 출력한다.

www.acmicpc.net

1. 문제 접근

문제에서 주어진 fibonacci(N)함수가 호출하는 fibonacci(0)과 fibonacci(1)의 횟수를 출력하는 문제이다. fibonacci(N) = fibonacci(N-1) + fibonacci(N-2) 이므로 fibonacci(N)이 fibonacci(0)와 fibonacci(1)을 호출하는 횟수는 아래와 같이 식을 만들어 볼 수 있다.

 

fibonacci(N)이 fibonacci(0)을 호출하는 횟수

        = fibonacci(N-1)이 fibonacci(0)을 호출하는 횟수 + fibonacci(N-2)가 fibonacci(0)을 호출하는 횟수

fibonacci(N)이 fibonacci(1)을 호출하는 횟수

        = fibonacci(N-1)이 fibonacci(1)을 호출하는 횟수 + fibonacci(N-2)가 fibonacci(1)을 호출하는 횟수

 

또한 매번 새롭게 계산하는 것을 막고자 다이나믹 알고리즘을 사용하여 이미 계산이 완료가 되었다면 저장후 다음에 계산없이 바로 사용할 수 있도록 하였다. 예를 들어 "fibonacci(N-1)이 fibonacci(0)을 호출하는 횟수"를 이전에 이미 계산하여 어딘가에 저장해 놓았다면 "fibonacci(N)이 fibonacci(0)을 호출하는 횟수"를 구할때, 해당 값을 바로 사용하면 된다.

 

시간복잡도 계산

다이나믹 알고리즘을 사용하였으므로 N이 2~40일때의 값만 한번씩 구해준다면 다음 계산에서는 이미 계산된 값들을 이용하여 O(1)시간에 문제를 해결할 수 있다. 즉, 아래 코드에서 setFiboCount(fiboCount, 2) ~ setFiboCount(fiboCount, 40) 함수가 한번씩만 호출되어 fiboCount[2] ~ fiboCount[40]에 적절한 값을 저장해주면 다음 계산부터는 O(1)시간에 문제를 계산할 수 있다는 것이다. 따라서 시간복잡도는 아래와 같으며 주어진 시간 0.25초는 매우 넉넉한 시간이 된다.

시간복잡도 = O(40 - 2 + 1) = O(39)

 

 

 

2. 코드

#include<iostream>
using namespace std;

#define MAX_N 40
#define INIT_COUNT -1

struct FiboCount {
    int fibo0;
    int fibo1;
    void set(int f0, int f1) {
        fibo0 = f0;
        fibo1 = f1;
    }
};

void initFiboCount(FiboCount* fiboCount, int size) {
    fiboCount[0].set(1, 0);
    fiboCount[1].set(0, 1);
    for (int i = 2; i < size; i++)
        fiboCount[i].set(INIT_COUNT, INIT_COUNT);
}

void setFiboCount(FiboCount* fiboCount, int n) {
    if (fiboCount[n].fibo0 != INIT_COUNT)
        return;
    setFiboCount(fiboCount, n - 1);
    setFiboCount(fiboCount, n - 2);
    fiboCount[n].fibo0 = fiboCount[n - 1].fibo0 + fiboCount[n - 2].fibo0;
    fiboCount[n].fibo1 = fiboCount[n - 1].fibo1 + fiboCount[n - 2].fibo1;
}

int main() {
    FiboCount fiboCount[MAX_N + 1];
    initFiboCount(fiboCount, MAX_N + 1);

    int T, N;
    cin >> T;
    for (int t = 0; t < T; t++) {
        cin >> N;
        setFiboCount(fiboCount, N);
        cout << fiboCount[N].fibo0 << " " << fiboCount[N].fibo1 << endl;
    }

    return 0;
}