https://www.acmicpc.net/problem/1074
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int cnt = 0;
static int r;
static int c;
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer tokenizer = new StringTokenizer(reader.readLine(), " ");
int n = Integer.parseInt(tokenizer.nextToken());
//r, c는 0-indexed
r = Integer.parseInt(tokenizer.nextToken());
c = Integer.parseInt(tokenizer.nextToken());
int size = (int) Math.pow(2, n);
solve(size, r, c);
System.out.println(cnt);
}
private static void solve(int size, int r, int c) {
if(size == 1)
return;
if(r < size/2 && c < size/2) {
solve(size/2, r, c);
}
else if(r < size/2 && c >= size/2) {
cnt += size * size / 4;
solve(size/2, r, c - size/2);
}
else if(r >= size/2 && c < size/2) {
cnt += (size * size / 4) * 2;
solve(size/2, r - size/2, c);
}
else {
cnt += (size * size / 4) * 3;
solve(size/2, r - size/2, c - size/2);
}
}
}
1. 문제
한수는 크기가 2N × 2N인 2차원 배열을 Z모양으로 탐색하려고 한다. 예를 들어, 2×2배열을 왼쪽 위칸, 오른쪽 위칸, 왼쪽 아래칸, 오른쪽 아래칸 순서대로 방문하면 Z모양이다.

N > 1인 경우, 배열을 크기가 2N-1 × 2N-1로 4등분 한 후에 재귀적으로 순서대로 방문한다.
다음 예는 22 × 22 크기의 배열을 방문한 순서이다.

N이 주어졌을 때, r행 c열을 몇 번째로 방문하는지 출력하는 프로그램을 작성하시오.
다음은 N=3일 때의 예이다.

입력
첫째 줄에 정수 N, r, c가 주어진다.
출력
r행 c열을 몇 번째로 방문했는지 출력한다.
제한
- 1 ≤ N ≤ 15
- 0 ≤ r, c < 2N
2. 풀이
해당 문제를 전수조사로 풀게 되면 시간초과가 발생한다. 따라서 계산으로 접근하여 divide and conquer를 해야 한다.
해당 문제는 Z 방향으로 움직인다. 배열 하나가 있으면 해당 배열을 4등분하여 좌상, 우상, 좌하, 우하 순으로 방문하게 된다.
r, c에 해당하는 숫자를 찾아야 한다. 각 등분의 가장 작은 숫자를 확인하여 이를 비교한다.
위의 그림이다. 해당 그림을 4등분하면 0-15, 16-31, 32-47, 48-63이다. 각 등분의 가장 작은 숫자는 0, 16, 32, 48이다.
즉, 전체 숫자의 개수를 4등분하고, 이를 계산해나가면서 r, c에 해당하는 숫자를 찾을 수 있다.
이에 따른 재귀함수는 다음과 같다.
private static void solve(int size, int r, int c) {
if(size == 1)
return;
if(r < size/2 && c < size/2) {
solve(size/2, r, c);
}
else if(r < size/2 && c >= size/2) {
cnt += size * size / 4;
solve(size/2, r, c - size/2);
}
else if(r >= size/2 && c < size/2) {
cnt += (size * size / 4) * 2;
solve(size/2, r - size/2, c);
}
else {
cnt += (size * size / 4) * 3;
solve(size/2, r - size/2, c - size/2);
}
}
r, c열의 숫자를 r, c의 크기에 따라 잘라준다. 예를 들어 위 그림의 2번째는 16부터 시작하여 Z 방문을 하는 4*4 배열이다.
'Coding Test' 카테고리의 다른 글
백준 7490 0 만들기 (Java) (2) | 2024.12.10 |
---|---|
백준 22251 빌런 호석 (Java) (1) | 2024.12.09 |
백준 14891 톱니바퀴 (Java) (0) | 2024.11.21 |
백준 1469 숌 사이 수열 (Java) (0) | 2024.11.17 |
백준 15558 점프 게임 (Java) (0) | 2024.11.14 |