티스토리 뷰

728x90

문제 링크

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


피보나치 수열은 보통 점화식으로 다음과 같이 표현된다.

f(n)=f(n2)+f(n1),(f(0)=0,f(1)=1)


이를 재귀함수로 구현하면



int fibo(int n) {
if (n == 0)
return 0;
if (n == 1)
return 1;
return fibo(n - 2) + fibo(n - 1);
}
view raw fibo.cpp hosted with ❤ by GitHub


이렇게 되고, 위의 코드에서 n=6인 경우 다음 그림처럼 함수가 전개된다.


재귀함수가 n을 인자로 호출되면 그 함수는 n1n2를 인자로 함수를 호출하고, 호출된 각 함수가 계속해서 함수를 두 개씩 호출하게 된다. 결국 시간복잡도가 O(2N)이므로 n 제한이 n<=45인 해당 문제의 경우 제한시간 내에 답을 구할 수 없다.




이를 해결하기 위해 반복해서 호출되는 부분에 주목해야한다.









네모 친 부분 트리들은 해당하는 n에 대해 최초로 답을 구했을 때, 어딘가에 답을 적어둔다면 다시 만났을 때 그 답을 활용 할 수 있으므로 더는 전개할 필요가 없게 된다. 이런 기법을 Memoization이라 하며,

이를 이용해 문제를 푸는 방식을 DynamicProgramming(동적계획법)이라 한다.


동적 계획법을 더 자세히 알고싶으면 다른 블로그를 활용하자.




동적 계획법을 이용하면 함수는 다음과 같이 호출된다.


어떤 n에 대해 최초 한번씩만 함수가 실행되므로 시간복잡도는 O(N)이다.



정답 코드


Bttom-up
#include <iostream>
using namespace std;
int n, d[50];
int main() {
d[1] = 1;
for (int i = 2; i <= 45; i++) {
d[i] = d[i - 1] + d[i - 2];
}
cin >> n;
cout << d[n];
}


Top-down
#include <iostream>
using namespace std;
int n, d[50] = {0, 1};
int fibo(int n){
if (n == 0) return 0;
if (n == 1) return 1;
if(d[n] != 0)
return d[n];
d[n] = fibo(n - 2) + fibo(n - 1);
return d[n];
}
int main() {
cin >> n;
cout << fibo(n);
}


728x90

'알고리즘 > 문제 풀이' 카테고리의 다른 글

[BOJ] 백준 1004 어린 왕자  (0) 2018.06.28
[BOJ] 백준 1003 피보나치 함수  (0) 2018.06.28
[BOJ] 백준 1002 터렛  (0) 2018.06.27
[BOJ] 백준 1001 A - B  (0) 2018.06.27
[BOJ] 백준 1000 A + B  (0) 2018.06.27
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/03   »
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
글 보관함