2 분 소요

1. 문제

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

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

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

다음 예는 2^2 × 2^2 크기의 배열을 방문한 순서이다.

N이 주어졌을 ,
r행 c열을  번째로 방문하는지 출력하는 프로그램을 작성하시오.

다음은 N=3 때의 예이다.

// 입력
첫째 줄에 정수 N, r, c가 주어진다.

// 출력
r행 c열을  번째로 방문했는지 출력한다.

// 제한
1  N  15
0  r, c < 2^N

// 예제 입력 1
2 3 1

// 예제 출력 1
11

// 예제 입력 2
3 7 7

// 예제 출력 2
63


2. 핵심 아이디어

  • z 모양을 구성하는 4가지 방향에 대해 차례대로 재귀적으로 호출


3. Python 문제풀이

# 방법 1
import sys

def z(n, x, y) :
  global result
  if x == r and y == c :
    print(int(result))
    exit(0)
  if n == 1 :
    result += 1
    return
  if not (x <= r < x + n and y <= c < y + n) :
    result += n * n
    return
  z(n / 2, x, y)
  z(n / 2, x, y + n / 2)
  z(n / 2, x + n / 2, y)
  z(n / 2, x + n / 2, y + n / 2)

result = 0
n, r, c = map(int, sys.stdin.readline().split())
z(2 ** n, 0, 0)

# 방법 2
import sys
input = sys.stdin.readline

n, r, c = map(int, input().split())

# z : 0,0을 기준으로 x, y의 숫자
def z(sz, x, y) :
  if sz == 1 :
    return 0
  sz //= 2
  for i in range(2) :
    for j in range(2) :
      if x < sz * (i + 1) and y < sz * (j + 1) :
        return (i*2+j) * sz * sz + z(sz, x-sz*i, y-sz*j)

print(z(2 ** n, r, c))


4. Java 문제풀이

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

class Main {
  static int count = 0;

  public static void main(String[] args) throws IOException {
    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());
    int size = (int) Math.pow(2, N);

    find(size, r, c);
    System.out.println(count);
  }

  private static void find(int size, int r, int c) {
    if (size == 1) {
      return;
    }
    if (r < size / 2 && c < size / 2) {
      find(size / 2, r, c);
    }
    else if (r < size / 2 && c >= size / 2) {
      count += size * size / 4;
      find(size / 2, r, c - size / 2);
    }
    else if (r >= size / 2 && c < size / 2) {
      count += (size * size / 4) * 2;
      find(size / 2, r - size / 2, c);
    }
    else {
      count += (size * size / 4) * 3;
      find(size / 2, r - size / 2, c - size / 2);
    }
  }
}

댓글남기기