https://www.acmicpc.net/problem/1003
1003번: 피보나치 함수
각 테스트 케이스마다 0이 출력되는 횟수와 1이 출력되는 횟수를 공백으로 구분해서 출력한다.
www.acmicpc.net
다음 소스는 N번째 피보나치 수를 구하는 C++ 함수이다.
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);
}
}
fibonacci(3)을 호출하면 다음과 같은 일이 일어난다.
1은 2번 출력되고, 0은 1번 출력된다. N이 주어졌을 때, fibonacci(N)을 호출했을 때, 0과 1이 각각 몇 번 출력되는지 구하는 프로그램을 작성하시오.
첫째 줄에 테스트 케이스의 개수 T가 주어진다.
각 테스트 케이스는 한 줄로 이루어져 있고, N이 주어진다. N은 40보다 작거나 같은 자연수 또는 0이다.
각 테스트 케이스마다 0이 출력되는 횟수와 1이 출력되는 횟수를 공백으로 구분해서 출력한다.
-----------------------------------------------------------------------------------------------------------------------------------
문제를 보자마자 메모이제이션이 떠올랐다. 동적 프로그래밍을 처음 공부할 때 피보나치로 배웠기 때문이었다. 만약 이 문제를 저 함수 그대로 카운팅해서 푼다면 분명 시간제한을 통과하지 못할 것이다.
일단 피보나치 함수를 토대로 0과 1이 불리는 규칙이 있는지 확인해보았다. 결과는,
0 = 1 0
1 = 0 1
2 = 1 1
3 = 1 2
4 = 2 3
5 = 3 5
이러했다. 0의 개수는 전 인덱스의 1의 개수이며 1의 개수는 전 인덱스 0과 1의 개수 합과 같다는 규칙이 있었다.
vector에 테스트 케이스를 저장 후, 메모이제이션은 그 중 최댓값까지의 인덱스에 값을 갖도록 했다.
인덱스에 들어갈 값은
zero[i] = one[i - 1];
one[i] = zero[i - 1] + one[i - 1]; << 이와 같은 식이면 될 것이다.
메모이제이션의 테스트케이스 인덱스만 뽑아오면 끝!
밑은 내 풀이코드이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 1003번: 피보나치 함수
// 0의 개수는 전 인덱스의 1의 개수
// 1의 개수는 전 인덱스 0과 1의 개수 합
int zero[10000];
int one[10000];
void solution(int num)
{
zero[0] = 1; one[0] = 0;
for (int i = 1; i < num + 1; ++i)
{
zero[i] = one[i - 1];
one[i] = zero[i - 1] + one[i - 1];
}
}
int main()
{
int num;
cin >> num;
vector<int> testCase;
for (int i = 0; i < num; ++i)
{
int temp;
cin >> temp;
testCase.push_back(temp);
}
solution(*max_element(testCase.begin(), testCase.end()));
for (int i = 0; i < num; ++i)
{
cout << zero[testCase[i]] << " " << one[testCase[i]] << endl;
}
}
[순열] 백준 15649 - N과 M1 (0) | 2022.04.05 |
---|---|
[브루트포스] 백준 6064 - 카잉 달력 (0) | 2022.03.30 |
[동적 프로그래밍] 백준 12865 - 평범한 배낭 (0) | 2022.03.29 |
[동적 프로그래밍] 백준 1463 - 1로 만들기 (0) | 2022.03.24 |
[동적 프로그래밍] DP의 유형과 예시 문제를 풀어보자. (0) | 2022.03.23 |