[백준] [C++] 1708번 볼록 껍질 (geometry)
2021. 7. 19. 21:29ㆍ알고리즘/백준
1. 문제
2. 풀이
선물포장 알고리즘
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<double, double> 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 |
'알고리즘 > 백준' 카테고리의 다른 글
[백준] [C++] 11266번 단절점 (dfs) (0) | 2021.07.21 |
---|---|
[백준] [C++] 1761번 정점들의 거리 (LCA, segment tree) (0) | 2021.07.20 |
[백준] [C++] 11689번 GCD(n, k) = 1 (오일러 피 함수) (0) | 2021.07.15 |
[백준] [C++] 3015번 오아시스 재결합 (stack) (0) | 2021.07.14 |
[백준] [C++] 2533번 사회망 서비스(SNS) (dfs, greedy) (0) | 2021.07.13 |