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 |
Tags
- Python
- 엘리스
- 알고리즘
- 입문
- Machine Learning Advanced
- Segmentation
- TEAM-EDA
- 큐
- 추천시스템
- 코딩테스트
- Image Segmentation
- 파이썬
- Recsys-KR
- pytorch
- 협업필터링
- eda
- Object Detection
- 프로그래머스
- DFS
- Semantic Segmentation
- DilatedNet
- 스택
- MySQL
- 튜토리얼
- 한빛미디어
- 3줄 논문
- 나는리뷰어다
- hackerrank
- TEAM EDA
- 나는 리뷰어다
Archives
- Today
- Total
TEAM EDA
[엘리스] 가장 가까운 두 점 찾기 (Big) 본문
가장 가까운 두 점 찾기 (Big)
2차원 평면에 n개의 점이 있다. 이 점들 중에서 그 거리가 가장 가까운 두 점 사이의 거리의 제곱을 출력하는 프로그램을 작성하시오. 단, 두 점 (x1, y1)과 (x2, y2) 사이의 거리는 $\sqrt{(x1-x2)^2 + (y1-y2)^2}$ 로 정의된다.
예를 들어, 4개의 점이 각각 (0, 3), (1, 1), (2, 2), (7, 1) 에 위치해 있다고 하면, 가장 가까운 두 점은 (1, 1)과 (2, 2)이며, 그 거리의 제곱은 2이다.
입력
첫째 줄에 점의 개수 nn이 주어진다. (2≤n≤100,000) 두 번째 줄부터 각 점의 x좌표, y좌표가 주어진다. 각 좌표는 정수이다.
출력
가장 가까운 두 점 사이의 거리의 제곱을 출력한다.
입력 예시
4
0 3
1 1
2 2
7 1
출력 예시
2
풀이
- 분할정복법을 이용한 풀이
- 왼쪽에서 최솟값 계산 (재귀)
- 오른쪽에서 최솟값 계산 (재귀)
- 중앙을 포함한 구간에서 최솟값 계산
- 재귀식
- 왼쪽과 오른쪽 중에서 더 작은 값을 d라고 표시
- 중앙을 포함한 구간은 양옆으로 d만큼의 거리내에 있는 값들임 (그 이상은 무조건 d가 넘을 것이니깐)
- 중앙점부터 거리 계산, 아래에 있는 점은 신경안쓰고 위로 d이내의 점들만 신경 (두 점의 거리기에 한쪽만 신경쓰면 모두 계산 됨, d는 위와 같은 논리)
- 계산할 값을 리스트(considerN)에 넣고, considerN에서 원소 하나(A)를 뽑아서 뒤의 12개 정도의 원소와 비교(B, C, D ...)
- 위와 같이 해도 되는 이유는 considerN에 들어가는 순서가 A랑 y축으로 가장 가까운 값이기 때문에
import sys
# 두 점간의 거리 계산
def getDistPoints(a, b) :
return (a[0] - b[0])**2 + (a[1] - b[1])**2
# 재귀식
def getDistBigInternal(points, start, end) :
if end - start <= 0 :
return 987987987987987
# 중앙 index
mid = (start + end) // 2
# 중앙의 x좌표
midX = (points[mid][0] + points[mid+1][0]) / 2
# 왼쪽과 오른쪽의 최솟값 계산
leftDist = getDistBigInternal(points, start, mid)
rightDist = getDistBigInternal(points, mid+1, end)
minDistValue = min(leftDist, rightDist)
temp = []
tempConsider = []
leftPtr = start
rightPtr = mid+1
# 중앙 index를 포함한 구간에서 최솟값 계산
while leftPtr <= mid or rightPtr <= end :
leftYval = points[leftPtr][1] if leftPtr <= mid else 987987987987987
rightYval = points[rightPtr][1] if rightPtr <= end else 987987987987987
# 다음으로 계산할 값을 tempConsider 에 저장
# 다음으로 계산할 값 : Y가 더 낮은 값이면서 d라는 구간내의 값
if leftYval <= rightYval :
temp.append(points[leftPtr])
leftPtr += 1
else :
temp.append(points[rightPtr])
rightPtr += 1
# tempConsider은 결국 d구간내에 있으면서, 최초의 포인트와 위쪽으로 가까운 순서대로 계속해서 들어가게 됨 !!!
if temp[-1][0] >= midX - minDistValue and temp[-1][0] <= midX + minDistValue :
tempConsider.append(temp[-1])
for i in range(start, end+1) :
points[i] = temp[i-start]
considerN = len(tempConsider)
result = 987987987987987
# tempConsider의 값이 A를 뽑고, A랑 y간의 거리가 가까운 B가 들어가고, B를 뽑고 B랑 가까운 C를 뽑기에 최소 6개정도만 보면 가까운 값들임 (위의 그림 참고)
for i in range(considerN) :
for j in range(1, 13) :
if i + j < considerN :
result = min(result, getDistPoints(tempConsider[i], tempConsider[i+j]))
return min(minDistValue, result)
def getDistBig(points) :
'''
n개의 점이 주어질 때, 가장 가까운 두 점 사이의 거리의 제곱을 반환하는 함수를 작성하세요.
예를 들어, 점이 4개가 있고, 각각의 좌표가 (0, 3), (1, 1), (2, 2), (7, 1) 이라면 points에는 다음과 같이 그 정보가 저장됩니다.
points = [ (0, 3), (1, 1), (2, 2), (7, 1) ]
이 때, 가장 가까운 두 점 사이의 거리의 제곱은 2입니다.
'''
pointsPrime = list(points)
pointsPrime.sort()
return getDistBigInternal(pointsPrime, 0, len(points)-1)
def main():
'''
이 부분은 수정하지 마세요.
'''
n = int(input())
points = []
for i in range(n) :
line = [int(x) for x in input().split()]
points.append( (line[0], line[1]) )
print(getDistBig(points))
if __name__ == "__main__":
main()
출처
'EDA Study > 알고리즘' 카테고리의 다른 글
[엘리스] 엘리스와 비밀번호 (0) | 2020.03.26 |
---|---|
[엘리스] 회의실 준비 (Big) (0) | 2020.03.25 |
[엘리스] Inversion counting (0) | 2020.03.25 |
[엘리스] 히스토그램 (0) | 2020.03.25 |
[엘리스] 색종이 만들기 (0) | 2020.03.25 |