문제
1003번: 피보나치 함수
각 테스트 케이스마다 0이 출력되는 횟수와 1이 출력되는 횟수를 공백으로 구분해서 출력한다.
www.acmicpc.net
문제이해
fibonacci(3)을 호출하면 다음과 같은 일이 일어난다.
fibonacci(3)은 fibonacci(2)와 fibonacci(1) (첫 번째 호출)을 호출한다.
fibonacci(2)는 fibonacci(1) (두 번째 호출)과 fibonacci(0)을 호출한다.
두 번째 호출한 fibonacci(1)은 1을 출력하고 1을 리턴한다.
fibonacci(0)은 0을 출력하고, 0을 리턴한다.
fibonacci(2)는 fibonacci(1)과 fibonacci(0)의 결과를 얻고, 1을 리턴한다.
첫 번째 호출한 fibonacci(1)은 1을 출력하고, 1을 리턴한다.
fibonacci(3)은 fibonacci(2)와 fibonacci(1)의 결과를 얻고, 2를 리턴한다.
1은 2번 출력되고, 0은 1번 출력된다.
N이 주어졌을 때, fibonacci(N)을 호출했을 때, 0과 1이 각각 몇 번 출력되는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다.
각 테스트 케이스는 한 줄로 이루어져 있고, N이 주어진다. N은 40 보다 작거나 같은 자연수 또는 0이다.
- T : 테스트 케이스
- N
출력
각 테스트 케이스마다 0이 출력되는 횟수와 1이 출력되는 횟수를 공백으로 구분해서 출력한다
풀이
시간제한이 없다면 주어진 피보나치 함수를 이용해 0과 1이 나올때 카운트하면 되지만 이 문제에는 0.25초의 시간 제한이 있습니다. 그렇기에 문제에 주어진 함수를 이용해서 풀이 하는 방법이 아닌 새로운 방법이 필요합니다.
먼저 N이 주어질 때, 0과 1의 갯수를 보게되면 다음 표와 같습니다.
N | 0의 갯수 | 1의 갯수 |
0 | 1 | 0 |
1 | 0 | 1 |
2 | 1 | 1 |
3 | 1 | 2 |
4 | 2 | 3 |
5 | 3 | 5 |
6 | 5 | 8 |
0과 1의 갯수가 증가하는 걸 보면 이 또한 피보나치 수열과 같음을 볼 수 있습니다. 따라서 재귀가 아닌 최적화 된 방법으로 피보나치 수열을 구해야 된다는 것을 알 수 있습니다. 이에 따라서 DP를 이용하여 중복되는 계산을 없애면 되겠습니다.
코드
import java.util.Scanner;
class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
int[] dp = new int[41];
dp[0] = 0;
dp[1] = 1;
dp[2] = 1;
for(int i = 3; i < 41; i++){
dp[i] = dp[i-1] + dp[i-2];
}
for(int i = 0; i < T; i++){
int N = sc.nextInt();
// N이 0과 1일 때 예외처리
if(N == 0)System.out.println("1 0");
else if(N == 1)System.out.println("0 1");
else System.out.println(dp[N-1]+ " " + dp[N]);
}
}
}
'Algorithm > 문제' 카테고리의 다른 글
[알고리즘] 백준 1004 : 어린 왕자 - JAVA (0) | 2023.04.13 |
---|---|
[알고리즘] 백준 1673 : 치킨 쿠폰 - JAVA (0) | 2023.04.12 |
[알고리즘] 백준 2606 : 바이러스 - JAVA (0) | 2023.04.10 |
[알고리즘] 백준 1541 : 잃어버린 괄호 - JAVA (0) | 2023.04.10 |
[알고리즘] 백준 5585 : 거스름돈 - JAVA (0) | 2023.04.06 |