BOJ 1074 : Z - https://www.acmicpc.net/problem/1074
딱 봤을 때 재귀로 풀이하면 되겠다! 했는데 바로 메모리 초과가 나버렸다. 이유를 분석해보니, n이 최대 15이기 때문에 최대 2^15의 row와 col이 생길 수 있다. 그래서 전체를 재귀로 탐색하면 메모리초과나 시간초과가 발생한다.
문제에서는 좌표(r,c)가 몇번째에 방문되는지 만 알아내면 되기 때문에, 굳이 좌표(r,c) 범위 밖의 영역은 재귀호출하지 않아도 된다.
이분탐색을 적용해서 풀이해야 한다. 이분탐색이란, 원하는 탐색범위를 두 부분으로 분할해서 찾는 방식이다. 이 문제에서는 4분탐색(?)이 되겠다.
4분할로 나눈 뒤, (r,c)가 존재하는 범위만 재귀 탐색을 진행한다. 아래 코드의 recursive() 함수가 재귀 호출을 진행하는데, 시작점과 length가 파라미터로 주어지면, 이 값을 통해 4개 영역으로 나눌 수 있다.
예시를 살펴보자. n이 3이라면 다음과 같은 결과를 나타내야한다.

첫 재귀호출의 파라미터로는 시작점은 (0,0), 길이가 8로 호출된다. 이 이차원 배열을 4분할 하면, 아래와 같이 나눌 수 있다.
(0,0)부터 시작해서 length 4, 카운트는 0부터 시작(0,4)부터 시작해서 length 4, 카운트는 16부터 시작(4,0)부터 시작해서 length 4, 카운트는 32부터 시작(4,4)부터 시작해서 length 4, 카운트는 48부터 시작여기서 (r,c)가 (3,1)이라면 첫번째 영역만 탐색하면 되고, (5,5)라면 네번째 영역만 탐색하면 되는 것이다! 카운트 정보는 계속 더해주며 재귀를 호출한다.
최종적으로 length가 2일 때 count를 센다. r,c를 만난다면 count를 출력하고 종료한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int r;
static int c;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] inputs = br.readLine().split(" ");
int N = Integer.parseInt(inputs[0]);
r = Integer.parseInt(inputs[1]);
c = Integer.parseInt(inputs[2]);
int pow_n = (int) Math.pow(2, N);
recursive(0,0, pow_n, 0);
}
public static void recursive(int si, int sj, int length, int cnt){ // si, sj는 시작점
if(length==2){
for (int i = si; i <= si+1; i++) {
for (int j = sj; j <= sj+1; j++) {
if(i==r && j==c){
System.out.println(cnt);
return;
}
cnt++;
}
}
return;
}
int half = length/2;
// si, sj, half, cnt
// si, sj+half, half, half*half*2
// si+half, sj, half, half*half
// si+half, sj+half, half, half*half*3
if(si<=r && r<si+half && sj<=c && c<sj+half){
recursive(si, sj, half, cnt);
}else if(si<=r && r<si+half && sj+half<=c && c<sj+length){
recursive(si, sj+half, half, cnt+half*half);
}else if(si+half<=r && r<si+length && sj<=c && c<sj+half){
recursive(si+half, sj, half, cnt+half*half*2);
}else{
recursive(si+half, sj+half, half, cnt+half*half*3);
}
}
}

✔ 알고리즘 분류 - 분할 정복, 재귀
✔ 난이도 - ⚪ Silver 1
딱히 없음