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

풀이1

최소 단위 배열을 만들어서 풀려고 했는데 너무 어려웠다. 구현 문제로 접근하면 안된다. 이전에 방문됐다고 간주되는 요소들을 한꺼번에 더하는 아이디어를 활용해 재귀로 풀어야 한다.

1 2
3 4

배열 영역을 위와 같은 순서로 분리해서 본다.

  • 영역을 구분하는 기준 좌표: 좌측 상단
  • size: 현재 탐색하고자 하는 영역의 한변의 길이
  • 이전에 방문됐다고 간주되는 요소들의 개수: size*size
    • 배열의 요소들이 순서대로 정렬됐기 때문에 개수들을 누적시켜주면서 counting한다.

누적 요소 개수 counting 여부

  • 현재 탐색하고자 하는 영역에
    • r, c가 있다면 영역을 4분할해서 다시 탐색
    • r, c가 없다면 영역 내에 존재하는 요소들의 개수를 counting해서 누적

counting 여부를 재귀로 구현해서 풀었다.

import sys
input = sys.stdin.readline

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

def Z(y, x, size):
    """
    영역을 4분할하는 단위 함수.
    영역의 기준점은 해당 영역의 가장 왼쪽 위 구석.
    y: r
    x: c
    """
    global ans

    # 검색 영역이 정확하게 (r, c)와 일치한다면 반환
    if y == r and x == c:
        print(ans)
        return

    #  r, c가 현재 사분면에 존재한다면
    if r < y + size and r >= y and c < x + size and c >= x:
        # 1사분면 탐색
        Z(y, x, size // 2)
        # 2사분면 탐색
        Z(y, x + size // 2, size // 2)
        # 3사분면 탐색
        Z(y + size // 2, x, size // 2)
        # 4사분면 탐색
        Z(y + size // 2, x + size // 2, size // 2)
    # 지나왔다고 간주되는 현재 영역들을 모두 ans에 누적시킨다.
    else:
        ans += size * size

# (0, 0), size=N^2부터 시작해서 검색 영역을 좁혀간다.
Z(0, 0, (1 << n))

풀이2

누적되는 요소들의 개수를 누적시킨다는 아이디어는 같다. 다른 점은 n을 감소시켜면서 (r, c)를 찾기 때문에 재귀보다 좀 더 빠르다.

import sys
input = sys.stdin.readline

n, r, c = map(int, input().split())
cnt = 0
while n > 0:
    n -= 1
    # 첫번째
    if r < 2**n and c < 2**n:
        continue
    elif r < 2**n and c >= 2**n:
        cnt += (2**n)*(2**n)*1
        c -= 2**n
    elif r >= 2**n and c < 2**n:
        cnt += (2**n)*(2**n)*2
        r -= 2**n
    else:
        cnt += (2**n)*(2**n)*3
        r -= 2**n
        c -= 2**n

print(cnt)

Leave a comment