[Baekjoon] 1074번 : Z
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);
}
}
}
댓글남기기