[백준] [C++] 1708번 볼록 껍질 (geometry)

2021. 7. 19. 21:29알고리즘/백준

1. 문제

 

1708번: 볼록 껍질 (acmicpc.net)

 

1708번: 볼록 껍질

첫째 줄에 점의 개수 N(3 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개의 줄에 걸쳐 각 점의 x좌표와 y좌표가 빈 칸을 사이에 두고 주어진다. 주어지는 모든 점의 좌표는 다르다. x좌표와 y좌표의 범

www.acmicpc.net

 

2. 풀이

 

선물포장 알고리즘

알고리즘 문제해결전략 552p

1) 가장 왼쪽 아래인 점을 찾아 컨벡스헐에 포함시킨다.

2) 이 점을 기준점으로 삼는다

3) 컨벡스헐에 마지막에 넣은것을 기준으로 가장 왼쪽에 있는 점을 찾아 포함시킨다.

4) 이 점이 처음 정한 기준점이 될때까지 3번을 반복한다.

 

 

 

3번에서 모든점을 검사해야한다.

따라서 점 H개가 컨벡스 헐에 포함되면

O(NH) 의 시간복잡도를 가지게 된다.

 

* hypot 함수는 빗변의 길이를 리턴 : hypot(변의 길이, 변의 길이)

 

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
#include <bits/stdc++.h>
 
#define vector2 pair<doubledouble>
 
using namespace std;
 
typedef vector<vector2> polygon;
int n;
 
 
vector2 sub(vector2 a, vector2 b) {
    return {a.first - b.first, a.second - b.second};
}
double ccw(vector2 a, vector2 b) {
    return a.first*b.second - a.second*b.first;
}
double ccw(vector2 p, vector2 a, vector2 b) {
    return ccw(sub(a, p), sub(b, p));
}
 
//points을 포함하는 최소 블록 다각형을 찾는다.
polygon gifWarp(const vector<vector2>& points) {
    int n = points.size();
    polygon hull;
    vector2 pivot = *min_element(points.begin(), points.end());
    hull.push_back(pivot);
 
    while(true) {
        vector2 ph = hull.back(), next = points[0];
        for(int i = 1; i < n; ++i) {
            // cross: 전에 선택한것을 기준으로 i번째 점이 후보에 반시계방향에 있을시 (왼쪽에 있을시) 업데이트.
            double cross = ccw(ph, next, points[i]);
            // dist: 평행할 때 지금보다 더 멀리 떨어저있는거라면 업데이트 시키라는 것.
            vector2 np = sub(next, ph);
            vector2 pp = sub(points[i], ph);
            double dist = hypot(np.first, np.second) - hypot(pp.first, pp.second);
            if(cross > 0 || (cross == 0 && dist < 0))
                next = points[i];
        }
        if(next == pivot) break;
        hull.push_back(next);
    }
    return hull;
}
 
int main() {
    cin>>n;
    polygon points;
    for(int i = 0; i < n; i++) {
        int a, b;
        cin>>a>>b;
        points.push_back({a, b});
    }
    points = gifWarp(points);
    cout<<points.size();
}
cs