문제
문제이해
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 |