ALGORITHM/BOJ

[백준] 1074 Z

0298 2021. 7. 13. 23:00

https://www.acmicpc.net/problem/1074

 

1074번: Z

한수는 크기가 2N × 2N인 2차원 배열을 Z모양으로 탐색하려고 한다. 예를 들어, 2×2배열을 왼쪽 위칸, 오른쪽 위칸, 왼쪽 아래칸, 오른쪽 아래칸 순서대로 방문하면 Z모양이다. 만약, N > 1이 라서

www.acmicpc.net

2021-07-13


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main1074 {
    public static int N, r, c;
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(bf.readLine());
        N = Integer.parseInt(st.nextToken());
        r = Integer.parseInt(st.nextToken());
        c = Integer.parseInt(st.nextToken());
        int answer = 0;
 
        int x = (1 << N) >> 1// init
        int y = x;
 
        while(N-- > 0) {
            int quarter =  (1 << N) * (1 << N);
            int move = (1 << N) >> 1;
            if (r < x && c < y) { // 1
                x -= move;
                y -= move;
            } else if (r < x && c >= y) { // 2
                x -= move;
                y += move;
                answer += quarter;
            } else if (r >= x && c < y) { // 3
                x += move;
                y -= move;
                answer += quarter*2;
            } else {
                x += move;
                y += move;
                answer += quarter*3;
            }
        }
 
        System.out.println(answer);
    }
}
cs

 

#문제풀이

분할정복 문제이다,,  개인적으로 이게 실버1? 인지 잘 모르겠는 문제이다..

1,2,3,4 분면을 나눠서 범위를 좁혀 나가는게 포인트인 문제이다. 

 

두 번째 예제 N == 3, r == 7, c == 7 을 기준으로 본다.

처음 초기값(x, y)은 정중앙인 2^N / 2 ((1<< N) >> 1) 으로 잡았다. 

그리고 4개의 사분면은 아래와 같은 방법으로 나눌 수 있다.

그리고 원하는 지점(7, 7)을 찾을 때까지, 해당 사분면에서 또 다시 4등분으로 나누면 된다.

또한, 여기서 각 사분면의 중심점이 새로 바뀐 것을 아래와 같이 확인할 수 있다.

이 때, 기준은 초기값과 같이  2^N / 2 ((1<< N) >> 1) (->move)이다.

 

1사분면  : (x -= 2, y-=2)

2사분면 : (x-=2, y+=2)

3사분면 : (x+=2, y-=2)

4사분면 : (x+=2, y+=2)

또한, 각 사분면이 움직일 때마다 더해야하는 수가 있다.

예를 들어, 내가 찾아야하는 (r, c)가 3사분면 쪽에 있다면, 1+2 사분면에서 계산해야하는 값들을 더한 후 이동해야 된다. 왜냐하면 우리가 어차피 3사분면에 이동하기 전까지 1+2사분면에서 카운팅 되는 숫자는 정해져있기 때문이다. 그래서 1사분면은 이동해야할 숫자를 더할 필요가 없다.

그리고 이것이 2^N (1<< N)*(1 << N)  (->quarter)인 것을 알 수 있다.

 

1사분면 : x

2사분면 : (1<<N)*(1<<N)

3사분면 : (1<<N)*(1<<N) * 2

4사분면 : (1<<N)*(1<<N) * 3

 

이것들을 N이 0이 될 때까지 반복하면 된다.