📌 풀이 과정
초기 접근 방식
2^(N-1) × 2^(N-1) 크기의 2차원 배열을 만들어서 Z순서를 기록하고 (r,c)의 값을 찾는 방식으로 접근했다.
하지만 N = 15인 경우, 2^14 × 2^14 크기의 배열이 필요하기 때문에 메모리 초과가 발생했다.
하하!!! 크리스마스 이브날에 푼 문제라 그런지 어떻게 재귀로 이끌어내야 할지 머리가 안돌아갔다...
분할 정복
N = 2 인 경우
0 | 1 |
2 | 3 |
N = 3 인 경우
0 | 1 | 4 | 5 |
2 | 3 | 6 | 7 |
8 | 9 | 12 | 13 |
10 | 11 | 14 | 15 |
N = 4 인 경우
N이 1 커질 때마다 사분면의 크기는 2배씩 커지고
배열을 4등분한 각 사분면은 이전 크기의 Z 방문 순서를 그대로 따른다는 것을 알 수 있다.
1. 현재 좌표 (r, c)가 어느 사분면에 위치하는지 계산한다.
r와 c 값을 기준으로 4개의 사분면 중 하나를 선택한다.
2. 선택된 사분면 이전까지의 방문 횟수를 누적한다.
방문 횟수 = (사분면 번호) x (사분면 크기)
3. (r, c)를 해당 사분면 내의 상대 좌표로 변환한다.
예를 들어, 2사분면 이라면 x좌표에서 배열의 절반만큼 더하기
4. 배열의 크기를 절반으로 줄이고, 상대 좌표를 재귀적으로 처리한다.
배열의 크기가 1 x 1이 되면, 누적된 방문 횟수를 출력하면 된다.
✨ 제출 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N, r, c;
static int ans = 0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
solve(0, 0, (1 << N));
}
private static void solve(int x, int y, int size) {
if (size == 1) {
System.out.println(ans);
return;
}
int newSize = size / 2;
if (r < x + newSize && c < y + newSize) {
solve(x, y, newSize);
}
else if (r < x + newSize && c >= y + newSize) {
ans += (newSize * newSize);
solve(x, y + newSize, newSize);
}
else if (r >= x + newSize && c < y + newSize) {
ans += (newSize * newSize * 2);
solve(x + newSize, y, newSize);
}
else {
ans += (newSize * newSize * 3);
solve(x + newSize, y + newSize, newSize);
}
}
}
'코딩 테스트 > Baekjoon' 카테고리의 다른 글
[백준] 12869. 뮤탈리스크 (DP/Java) (0) | 2025.01.20 |
---|---|
[백준] 1520. 내리막길 (DP/Java) (0) | 2024.12.26 |
[백준] 2096. 내려가기 (DP/Java) (1) | 2024.12.19 |
[백준] 13397. 구간 나누기 2 (이분탐색/Java) (0) | 2024.12.12 |
[백준] 16236. 아기상어 (그래프/Java) (0) | 2024.11.12 |