문제
메시는 축구 선수이다. 메시는 기분이 좋다.
messi(1): Messi
messi(2): Messi Gimossi
messi(3): Messi Gimossi Messi
messi(4): Messi Gimossi Messi Messi Gimossi
messi(5): Messi Gimossi Messi Messi Gimossi Messi Gimossi Messi
메시의 외침은 피보나치 수열과 유사하게 정의된다. messi(N)은 messi(N-1), 공백, messi(N-2)을 차례로 이어붙여서 만든 문자열이다.
욱제는 N이 충분히 클 때, messi(N)의 M번째 글자가 뭔지 궁금해졌다.
입력
정수 M이 주어진다. (1 ≤ M ≤ 230-1)
출력
N이 충분히 클 때, messi(N)의 M번째 글자가 공백(' ')이 아닐 경우에는 그 글자를 출력한다.
M번째 글자가 공백(' ')일 경우에는 Messi Messi Gimossi를 출력한다.
정답은 대소문자를 구분하므로 출력에 주의한다.
💡 풀이
위의 예시에서 보이는 것과 같이 messi(N)의 길이는 다음과 같이 정의될 수 있다.
$$messi(N) = messi(N-1) + 1 + messi(N-2)$$
그럼 주어진 M에 대해 다음과 같은 3가지의 경우로 나눌 수 있다.
- M이 messi(N-1)보다 같거나 작은 경우. 즉, messi(N-1) 안에 있는 경우
- M이 messi(N-1)+1인 경우. 이 경우에는 공백에 해당된다.
- M이 messi(N-1)+1보다 큰 경우. 이 경우는 messi(N-2) 안에 있는 경우이다.
처음에 M의 크기를 보고 몇 번째의 messi에 해당하는지 확인한 뒤, 위의 3가지 경우를 확인해가며 N을 줄여나가 N이 1 혹은 2가 되는 경우까지 재귀를 통해 진행시킨다. N이 1 혹은 2에 도달하면 줄여왔던 길이 M을 통해 해당하는 문자를 구할 수 있다.
즉, 여기서 base case가 N=1 혹은 N=2가 되는 경우 또는 공백을 만난 경우이다.
전체적인 코드는 다음과 같다.
import java.util.Scanner;
public class Q17297 {
public static long[] messi = new long[1000];
public static int flag = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long M = sc.nextLong();
messi[1] = 5;
messi[2] = 13;
int index = 3;
// 현재 주어진 M이 해당하는 messi의 index값(N값) 찾기
while(true){
messi[index] = messi[index-1]+1+messi[index-2];
if(messi[index]>M){
break;
}
index++;
}
find(index, M);
}
public static void find(int index, long n){
if(flag==1){
System.out.println("Messi Messi Gimossi");
return;
}
if(index==1){
System.out.println("Messi".charAt((int)n-1));
return;
}
else if(index==2){
// Messi Gimossi에서 공백을 만났을 경우
if(n==6){
System.out.println("Messi Messi Gimossi");
}
else
System.out.println("Messi Gimossi".charAt((int)n-1));
return;
}
// 앞 쪽에 해당하는 경우
if(messi[index-1]>=n){
find(index-1, n);
}
// 중간의 공백에 해당하는 경우
else if(messi[index-1]+1==n){
flag=1;
find(index-1, n);
}
// 뒤 쪽에 해당하는 경우
else{
// 앞의 messi(n-1)과 공백의 크기를 전체 길이에서 빼주어야 한다.
find(index-2, n-messi[index-1]-1);
}
}
}
'알고리즘 > BOJ' 카테고리의 다른 글
[BOJ] 12869 : 뮤탈리스크(Java) (0) | 2023.01.12 |
---|---|
[BOJ] 2096 : 내려가기(Java) (0) | 2023.01.11 |
[BOJ] 2630 : 색종이 만들기(Java) (0) | 2023.01.04 |
[BOJ] 18352 : 특정 거리의 도시 찾기(Java) (0) | 2022.11.19 |
[BOJ] 15900 : 나무 탈출(Java) (1) | 2022.11.17 |