#문제

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

 

2261번: 가장 가까운 두 점

첫째 줄에 자연수 n(2 ≤ n ≤ 100,000)이 주어진다. 다음 n개의 줄에는 차례로 각 점의 x, y좌표가 주어진다. 각각의 좌표는 절댓값이 10,000을 넘지 않는 정수이다. 같은 점이 여러 번 주어질 수도 있다.

www.acmicpc.net

 

#작성 코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
struct Point{
    int x, y;
};
 
// 두 점간의 거리^2를 구하는 함수 
long long int distance(Point &a, Point &b){
    long long int dist = (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
    return dist;
}
 
// x좌표를 기준으로 정렬하기 위한 comp함수 
struct comp{
    bool compX;
    comp(bool b):compX(b){}
    bool operator()(Point &a, Point &b){
        return (this->compX?a.x<b.x:a.y<b.y);
    }
};
 
// n개의 점들 중 최단거리를 구하기 위한 함수 
long long int closestPair(vector<Point>::iterator it, int n){
    if( n==2 ){
        return distance(it[0], it[1]);
    }
    else if( n==3 ){
        return min(distance(it[0],it[1]), min(distance(it[1],it[2]), distance(it[0], it[2])));
    }
    
    // n이 3 이상일때 x좌표를 기준으로 기준선을 정한다.
    // 중간에 위치한 두 점의 x좌표의 평균값을 기준선으로 한다. 
    int line =  (it[n/2-1].x + it[n/2].x)/2;
    // line의 좌,우 중에서 최소 거리인 d를 계산한다.
    long long int d = min( closestPair(it, n/2), closestPair(it+n/2, n-n/2) );
    
    vector<Point> mid;
    mid.reserve(n);
    
    for(int i=0; i<n; i++){
        int t = line-it[i].x;
        // x좌표 차이^2이 d보다 작다면 탐색해본다. 
        if( t*< d ){
            mid.push_back(it[i]);    // 탐색할 대상을 mid에 추가한다 
        }
    }
    
    // line에서 d미만으로 떨어져있는 점들을 y좌표 기준으로 정렬한다. 
    sort(mid.begin(), mid.end(), comp(false));
    // mid에 존재하는 점들 중 d 미만의 dist를 가진다면 d에 업데이트
    int MIDSIZE = mid.size();
    for(int i=0; i<MIDSIZE-1; i++){
        for(int j=i+1; j<MIDSIZE&&(mid[i].y-mid[j].y)*(mid[i].y-mid[j].y) < d; j++){
            d = min( d, distance(mid[i], mid[j]) );
        }
    } 
    return d;
}
 
int main(){
    int n;
    cin>>n;
    
    vector<Point> vp(n);
    for(vector<Point>::iterator it=vp.begin(); it!=vp.end(); it++){
        cin>> it->>> it->y;
    }
    
    sort(vp.begin(), vp.end(), comp(true));
    cout<<closestPair(vp.begin(), n);
    return 0;
}
cs

##

분할정복 아이디어는 많이 풀면 잘 떠오르겠지...

많이많이 풀어보자

https://casterian.net/archives/92 참고하였다.

'BOJ' 카테고리의 다른 글

BOJ 2618번 :: 경찰차  (0) 2020.02.01
BOJ 10942번 :: 팰린드롬?  (0) 2020.01.28
BOJ 4781번 :: 사탕가게  (0) 2020.01.23
BOJ 7579번 :: 앱  (0) 2020.01.23
BOJ 1520번 :: 내리막 길  (0) 2020.01.09

+ Recent posts