https://www.acmicpc.net/problem/1074
1074번: Z
한수는 크기가 2N × 2N인 2차원 배열을 Z모양으로 탐색하려고 한다. 예를 들어, 2×2배열을 왼쪽 위칸, 오른쪽 위칸, 왼쪽 아래칸, 오른쪽 아래칸 순서대로 방문하면 Z모양이다. N > 1인 경우, 배열을
www.acmicpc.net
고민을 했지만 결국 해결책을 얻지 못했다.
처음 풀어볼 때, 재귀쪽으로 2 X 2까지 나누어진 뒤에 무언가 진행되어야한다라는 방식으로 고민했지만 항상 재귀와 관련한 문제만 만나면 블루스크린 뜨는 것 마냥 머리가 돌아가다 만다...
이 문제도 다른 분의 해결책을 참고해서 풀었다.
2가지 방법으로 풀 수 있었다.
1. 분할정복
2. 재귀
분할정복
- N X N 배열을 4개의 사분면으로 나눠서 생각하는 방법
- 8 X 8 배열에서 목표 좌표 (a, b)를 (7,7)이라 가정하자
- 첫 번째로 쪼갤 때(N = 3)
- row : 7 >= 2 ^ 2
- column : 7 >= 2 ^ 2
- 둘다 N X N의 절반보다 크기떄문에 4사분면에 위치한다는 것을 알 수 있다.
- 이때, 각 사분면의 시작값? 횟수는 이와 같다.
- 각 사분면의 갯수는 (N / 2) X (N / 2), 즉 4 *4 = 16 이다.
- 1 사분면 : 0
- 2 사분면 : 16
- 3 사분면 : 32
- 4 사분면 : 48
- 이러한 방식으로 2 X 2 까지 쪼갠 뒤 계산하면 구할 수 있다.
import sys
input = sys.stdin.readline
N, r, c = map(int, input().split())
ans = 0
while N != 0:
N -= 1
# 1사분면
if r < 2 ** N and c < 2 ** N:
ans += ( 2 ** N ) * ( 2 ** N ) * 0
# 2사분면
elif r < 2 ** N and c >= 2 ** N:
ans += ( 2 ** N ) * ( 2 ** N ) * 1
c -= ( 2 ** N )
# 3사분면
elif r >= 2 ** N and c < 2 ** N:
ans += ( 2 ** N ) * ( 2 ** N ) * 2
r -= ( 2 ** N )
# 4사분면
else:
ans += ( 2 ** N ) * ( 2 ** N ) * 3
r -= ( 2 ** N )
c -= ( 2 ** N )
print(ans)
재귀
2 * 2 배열 기준, (r, c) 가 2배가 됨에 따라 해당 위치의 방문값은 4배가 된다.
EX) 8 (2, 0) -> 32 (4,0)
- 2 * (r % 2) + (c % 2) : 0, 1, 2, 3 을 더해주는 용도
- 4*sol(N-1, int(r/2), int(c/2)) : 좌표값을 2배씩 나눴을 때, 당시의 결과값을 구하기 위한 재귀함수
- x,y 값이 2배씩 증감되면 결과값이 4배 증감하는 법칙을 사용한 것
이해하는데 조금 어려웠지만 정말 이게 재귀구나 라는 걸 느낄 수 있었다.
진짜 유연하게 재귀함수를 구현하는 게 신기하고 DP나 재귀를 계속 연습해야겠다.
import sys
input = sys.stdin.readline
N, r, c = map(int, input().split())
def sol(N, r, c):
if N == 0:
return 0
return 2*(r%2)+(c%2) + 4*sol(N-1, int(r/2), int(c/2))
# 4*sol(N-1, int(r/2), int(c/2))
print(sol(N, r, c))
해설 출처 : https://ggasoon2.tistory.com/11
'코딩 테스트' 카테고리의 다른 글
[백준, DP] 12865 평범한 배낭 (0) | 2025.01.07 |
---|---|
[백준, DP] 1149 RGB 거리 (0) | 2024.12.31 |
[백준, 브루트포스] 1107_리모콘 (0) | 2024.04.02 |
[백준, 그래프] 1012_유기농 배추 (0) | 2024.04.02 |
[백준, Hash] 1620_나는야 포켓몬 마스터 (1) | 2024.03.28 |