[Java] BOJ1074, 백준 - Z

2022. 2. 15. 17:55·알고리즘/문제풀이
728x90

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

 

1074번: Z

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

www.acmicpc.net

 

개인적으로 분할정복에 약해서 좀 어려웠던 문제이다.

아이디어를 얻어서 문제를 풀었다기보다는, 그림을 그려가며 규칙을 발견해서 이에 맞춘 느낌?

 

이 문제를 N별로 찬찬히 들여다보면 다음과 같은 규칙을 발견할 수 있음

빨>주>노>초 순으로 1>2>3>4

 

1. N=1일 때

또한 왼쪽 위 칸을 기준으로 인덱스는

 

2. N=2일 때

왼쪽 위 영역에서 0,0좌표의 숫자를 기준으로 한다.

 

3. N=3일 때

 

그러면 인덱스를 기준으로 규칙성을 발견할 수 있다.

네 구역으로 나눴을 때 가장 왼쪽 위 칸의 시작은 0에 2^(2*(N-1))이 된다.

 

그리고 빨주노초 칸의 인덱스를 보면

 

빨간색 칸

i : 0~2^(n-1), j: 0~2^(n-1)

 

주황색 칸

i : 0~2^(n-1), j: 2^(n-1)~2^n

 

노랑색 칸

i : 2^(n-1)~2^n, j : 0~2^(n-1)

 

초록색 칸

i : 2^(n-1)~2^n, j: 2^(n-1)~2^n

 

근데 여기서 인덱스가 0미만이거나 2^n이상인 경우는 없기 때문에 인덱스 비교조건은 더 간단하다.

이 규칙을 가지고 쇽쇽 1/4씩 줄어들면 시간복잡도 n만에 풀 수 있다.

 

이 규칙 그대로 코드를 짜면 다음과 같다.

import java.io.*;
import java.util.*;

public class Main {

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		int n = Integer.parseInt(st.nextToken());
		long r = Integer.parseInt(st.nextToken());
		long c = Integer.parseInt(st.nextToken());

		go(r, c, n, 0);

	}

	private static void go(long i, long j, int n, int add) {
		if (n == 1) {
			System.out.println(add + 2 * i + j);
			return;
		}

		int idx = (int) Math.pow(2, n - 1);
		int addnum = (int) Math.pow(2, 2 * (n - 1));
		if (i < idx && j < idx) {
			// 왼쪽위
			go(i, j, n - 1, add);
		} else if (i < idx && j >= idx) {
			// 오른쪽 위
			go(i, j - idx, n - 1, add + addnum);
		} else if (i >= idx && j < idx) {
			// 왼쪽 아래
			go(i - idx, j, n - 1, add + addnum * 2);
		} else if (i >= idx && j >= idx) {
			// 오른쪽 아래
			go(i - idx, j - idx, n - 1, add + addnum * 3);
		}

	}
}

 

보니깐 조건문 부분을 좀 더 줄일 수 있는데,

코드는 더 짧긴 한데 나는 갠적으로 위코드가 좀더 보기좋은 것 같다.

import java.io.*;
import java.util.*;

public class Main {

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		int n = Integer.parseInt(st.nextToken());
		int r = Integer.parseInt(st.nextToken());
		int c = Integer.parseInt(st.nextToken());

		go(r, c, n, 0);

	}

	private static void go(int i, int j, int n, int add) {
		if (n == 1) {
			System.out.println(add + 2 * i + j);
			return;
		}

		int idx = (int) Math.pow(2, n - 1);
		int iflag = (i >= idx) ? 1 : 0;
		int jflag = (j >= idx) ? 1 : 0;

		go(i - iflag * idx, j - jflag * idx, n - 1, add + (int) Math.pow(2, 2 * (n - 1)) * (iflag * 2 + jflag));
	}
}

'알고리즘 > 문제풀이' 카테고리의 다른 글

[Java] BOJ9466, 백준 - 텀 프로젝트  (0) 2022.02.16
[Java] BOJ2812, 백준 - 크게 만들기  (0) 2022.02.16
[Java] BOJ5052, 백준 - 전화번호 목록  (0) 2022.02.15
[Java] BOJ14567, 백준 - 선수과목 (Prerequisite)  (0) 2022.02.14
[Java] BOJ16973, 백준 - 직사각형 탈출  (0) 2022.02.09
'알고리즘/문제풀이' 카테고리의 다른 글
  • [Java] BOJ9466, 백준 - 텀 프로젝트
  • [Java] BOJ2812, 백준 - 크게 만들기
  • [Java] BOJ5052, 백준 - 전화번호 목록
  • [Java] BOJ14567, 백준 - 선수과목 (Prerequisite)
kkap999
kkap999
IT에 관심 가득한 갑갑이의 개발&스터디 블로그
  • kkap999
    갑갑이의 개발세상
    kkap999
    • 분류 전체보기 (95)
      • Backend (1)
        • Java&Spring&Servlet (8)
        • DB (0)
      • 알고리즘 (78)
        • 문제풀이 (70)
        • 자료구조 (6)
        • 그 외 (2)
      • App&FE (3)
        • FE (1)
        • Flutter (2)
      • Computer Science (0)
        • 네트워크 (0)
        • 컴퓨터기초 (0)
      • Cloud (0)
        • AWS (0)
        • Azure (0)
        • gcp (0)
      • 잡담&일상 (4)
        • 일상 (1)
        • 잡담 (2)
        • 음악 (1)
  • 태그

    알고리즘
    BOJ
    BOJ15649
    백준
    N과M(1)
  • 링크

    • github
  • 인기 글

  • 최근 글

  • 07-26 13:27
  • 전체
    오늘
    어제
  • 반응형
  • hELLO· Designed By정상우.v4.10.3
kkap999
[Java] BOJ1074, 백준 - Z
상단으로

티스토리툴바