Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- computer vision
- 백준
- 그래프이론
- Backpropagation
- forward
- git commit
- WSI
- git add
- Branch
- 밑바닥부터 시작하는 딥러닝 1
- BFS
- Segment Anything
- DFS
- Heap
- 파이썬
- 알고리즘
- Merge
- 병리
- 분할정복
- git branch
- cv
- 오차역전파
- 그래프
- Git
- 딥러닝
- add
- Pathology
- git merge
- conflict
- Python
Archives
- Today
- Total
나만의 길
[백준] 1074번 Z - (Python) 본문
반응형
https://www.acmicpc.net/problem/1074
1074번: Z
한수는 크기가 2N × 2N인 2차원 배열을 Z모양으로 탐색하려고 한다. 예를 들어, 2×2배열을 왼쪽 위칸, 오른쪽 위칸, 왼쪽 아래칸, 오른쪽 아래칸 순서대로 방문하면 Z모양이다. N > 1인 경우, 배열을
www.acmicpc.net
분할정복 문제. 2^N x 2^N 사각형을 계속해서 4등분을 해서 해당하는 좌표의 값을 불러오는 문제입니다.여기서 Key포인트는 '모든작업을 하면 안된다' 입니다. Divide & Conquer 방식으로 해당 좌표에 포함되는 부분만 나누어서 문제를 해결해야 메모리초과없이 문제를 해결할 수 있습니다.
분할정복에 대한 개념이 확실히 잡히지 않은상태에서 단순 재귀로 구현해서, 계속된 메모리초과가 발생했었습니다. 따라서 분할정복 개념을 배우고 이를 적용하는 문제로 적합한거 같습니다.
※ 고려사항
1. 분할정복 규칙성 찾기
1. 분할정복 규칙성 찾기
해당문제는 좌표가 가리키는 사분면을 1, 2, 3, 4분면으로 구분한 뒤, 계속해서 찾아줘야합니다.
그림을 통해 쉽게 이해해 보겠습니다.
예를 들어, N = 3, r = 0, c = 0 일때, 즉 0의 값을 찾기위한 과정은 다음과 같습니다. 계속해서 4등분을해서, 최종적으로 노란색 사각형이 되면 종료됩니다. 즉, N의 값을 1씩 감소시켜, N = 0이 되었을 경우 종료되게끔 하면 됩니다.
사분면은 다음과 같이 구분합니다. 그림 퀄리티가 낮아서 죄송합니다..
그렇다면 사분면을 구분하는 규칙은 무엇일까요? 다음 그림을 통해 이해해봅시다.
즉, 2^(n-1) x 2^(n-1) x (0, 1, 2, 3) 으로 이루어집니다. 따라서 다음과 같이 정리할 수 있습니다.
0 : 1사분면, 1: 2사분면, 2 : 3사분면, 3 : 4사분면
왼쪽 이미지에서 4사분면 48은 N=3이므로 계산해보면 2^2 x 2^2 x 3 = 4 x 4 x 3 = 48입니다.
따라서 N을 1씩 줄여나가면서 해당 좌표가 해당하는 사분면만 계속해서 계산해주면 됩니다.
그렇다면 좌표를 구별하는 특징을 살펴보겠습니다.
사분면이 바뀌는 경계점을 고려합니다. N = 2일때는 (0, 0), (2, 0), (0, 2) (2, 2) 즉, N의 값을 넘으면 사분면이 바뀌게 됩니다. 또 계속해서 N이 줄어듬에 따라 사각형이 줄어들기 때문에, 우리가 찾으려는 좌표도 수정해야 합니다.
예를들어, N = 3, (7, 7)의 좌표는 63입니다. 해당좌표는 4사분면에 있기 때문에, 4사분면 사각형만 고려합니다. 그렇게 되면 다음 그림과 같이 됩니다.
(7, 7) 의 좌표가 (3, 3) 으로 줄고 N = 2가 되었습니다. 즉. 2^N 만큼 좌표가 줄어들게 됩니다.
이제 코드를 통해 확인해봅시다.
import sys
input = sys.stdin.readline
n, c, r = map(int, input().split())
cnt = 0
while n != 0:
n -= 1
# 1사분면
if c < pow(2, n) and r < pow(2, n): # 사분면 구별
cnt += pow(2, n) * pow(2, n) * 0 # 숫자 규칙
# 2사분면
elif c < pow(2, n) and r >= pow(2, n):
cnt += pow(2, n) * pow(2, n) * 1
r -= pow(2, n) # 좌표 변경 규칙
# 3사분면
elif c >= pow(2, n) and r < pow(2, n):
cnt += pow(2, n) * pow(2, n) * 2
c -= pow(2, n)
# 4사분면
else:
cnt += pow(2, n) * pow(2, n) * 3
c -= pow(2, n)
r -= pow(2, n)
print(cnt)
해당문제를 단순히 재귀로 구현하여, 메모리 초과가 발생했습니다.
메모리초과 코드
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10000)
n, c, r = map(int, input().split())
matrix = [[0] * pow(2,n) for _ in range(pow(2,n))]
cnt = 0
def z(n, x, y):
global cnt
real_y = y
if n == 1:
for _ in range(pow(2, n)):
for _ in range(pow(2, n)):
matrix[x][y] = cnt
y+=1
cnt+=1
x+=1
y = real_y
return
else:
z(n-1, x, y)
z(n-1, x, y + pow(2,n-1))
z(n-1, x + pow(2, n-1), y)
z(n-1, x + pow(2, n-1), y + pow(2, n-1))
z(n, 0, 0)
print(matrix[c][r])
분할정복의 개념을 자료구조 Divide & Conquer으로 학습했으나, 코드로 구현하기에는 또 어려움이 있었습니다. 분할정복 문제는 반드시 많이 연습하여 체화시켜야 한다고 느낀 문제였습니다. 시간초과나 메모리 초과를 해당 방법으로 구현하지 못하면 반드시 피할 수 없기 때문입니다. 다른 분할정복 문제로 다시 찾아오겠습니다.
설명의 오류나, 궁금하신점은 언제든 피드백 해주시면 감사하겠습니다 ^~^
반응형
'Algorithm > Divide & Conquer' 카테고리의 다른 글
[백준] 1992번 쿼드트리 - (Python) (0) | 2023.01.15 |
---|---|
[백준] 1780번 종이의 개수 - (Python) (0) | 2023.01.14 |
Comments