※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 9240번 문제인 로버트 후드이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/9240
9240번: 로버트 후드
첫째 줄에 로버트 후드가 발사한 화살의 수 C (2 ≤ C ≤ 100,000)가 주어진다. 다음 C개 줄에는 화살의 좌표가 주어진다. 좌표는 정수이고, 절댓값은 1,000을 넘지 않는다.
www.acmicpc.net
주어지는 점들로 convex hull을 구하고, 이를 구성하는 점들 사이 거리의 최댓값을 rotating calipers 알고리즘 등을 이용해 구하는 문제이다.
글쓴이는 convex hull을 Andrew's algorithm을 이용해 구했고, 두 직선의 기울기의 비교를 정수 자료형의 연산만으로 수행하는 코드를 작성해 문제를 해결했다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef long double ld;
int N;
pll points[100000];
vector<pll> upperhull; // leftmost x의 lowermost y부터 rightmost x의 uppermost y까지
vector<pll> lowerhull;
int CCW(pll& A, pll& B, pll& C) {
ll ccw = (B.first - A.first) * (C.second - A.second) - (B.second - A.second) * (C.first - A.first);
if (ccw > 0) return 1;
else if (ccw < 0) return -1;
else return 0;
}
void andrew_algorithm() {
sort(points, points + N);
//upperhull
for (int i = 0; i < N; i++) {
auto& cur = points[i];
int cursize = upperhull.size();
while (cursize > 1) {
auto& L = upperhull[cursize - 2], & M = upperhull[cursize - 1];
if (CCW(L, M, cur) != -1) upperhull.pop_back(), cursize--;
else break;
}
upperhull.emplace_back(cur);
}
//lowerhull
for (int i = 0; i < N; i++) {
auto& cur = points[i];
int cursize = lowerhull.size();
while (cursize > 1) {
auto& L = lowerhull[cursize - 2], & M = lowerhull[cursize - 1];
if (CCW(L, M, cur) != 1) lowerhull.pop_back(), cursize--;
else break;
}
lowerhull.emplace_back(cur);
}
}
ll dfunc(pll& p1, pll& p2) {
return (p1.first - p2.first) * (p1.first - p2.first) + (p1.second - p2.second) * (p1.second - p2.second);
}
ld rotating_calipers() {
int u = 0, uend = upperhull.size(), l = lowerhull.size() - 1;
ll mx = dfunc(upperhull[u], lowerhull[l]);
while (u < uend - 1 && l > 0) {
if (upperhull[u].first == upperhull[u + 1].first) u++;
else if (lowerhull[l].first == lowerhull[l - 1].first) l--;
else {
ll dx1 = upperhull[u + 1].first - upperhull[u].first, dy1 = upperhull[u + 1].second - upperhull[u].second;
ll dx2 = lowerhull[l].first - lowerhull[l - 1].first, dy2 = lowerhull[l].second - lowerhull[l - 1].second;
if (dy1 * dx2 > dx1 * dy2) u++;
else l--;
}
mx = max(mx, dfunc(upperhull[u], lowerhull[l]));
}
while (u < uend - 1) {
u++;
mx = max(mx, dfunc(upperhull[u], lowerhull[l]));
}
while (l > 0) {
l--;
mx = max(mx, dfunc(upperhull[u], lowerhull[l]));
}
return sqrt(mx);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout << fixed;
cout.precision(10);
cin >> N;
for (int i = 0; i < N; i++) cin >> points[i].first >> points[i].second;
andrew_algorithm();
cout << rotating_calipers();
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 2244 // C++] 민코프스키 합 (0) | 2023.05.22 |
---|---|
[BOJ 10254 // C++] 고속도로 (0) | 2023.05.21 |
[BOJ 1708 // C++] 볼록 껍질 (0) | 2023.05.19 |
[BOJ 15235 // C++] Olympiad Pizza (0) | 2023.05.18 |
[BOJ 15237 // C++] Cipher (0) | 2023.05.17 |