※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 7420번 문제인 맹독 방벽이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/7420
7420번: 맹독 방벽
첫 번째 줄에 건물의 수 N과 거리 L이 주어진다. (3 ≤ N ≤ 1000, 1 ≤ L ≤ 1000, N과 L은 정수) 다음 N개의 줄에 거쳐 건물의 좌표 Xi와 Yi가 정수로 주어진다. (-10000 ≤ Xi, Yi ≤ 10000) 모든 건물의 좌
www.acmicpc.net
주어진 점들을 모두 포함하는 가장 둘레가 짧은 다각형은 convex hull과 같다는 점을 떠올리자.
위와 같은 관찰에서 문제에서 구하는 방벽은 convex hull로부터 거리가 (convex hull의 바깥방향으로) L만큼 떨어진 폐곡선으로 나타남을 알 수 있다. 이 곡선의 길이는 (convex hull의 둘레) + (반지름이 L인 원의 둘레)와 같이 구할 수 있다는 점을 관찰하자.
아래는 제출한 소스코드이다.
#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; ll L;
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);
}
}
ld ans, PI = acos(-1);
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout << fixed;
cout.precision(0);
cin >> N >> L;
for (int i = 0; i < N; i++) cin >> points[i].first >> points[i].second;
andrew_algorithm();
for (int i = 0; i + 1 < upperhull.size(); i++) {
ans += hypot(upperhull[i].first - upperhull[i + 1].first, upperhull[i].second - upperhull[i + 1].second);
}
for (int i = 0; i + 1 < lowerhull.size(); i++) {
ans += hypot(lowerhull[i].first - lowerhull[i + 1].first, lowerhull[i].second - lowerhull[i + 1].second);
}
cout << ans + 2 * PI * L;
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 26072 // C++] 곰곰이와 시소 (0) | 2022.12.01 |
---|---|
[BOJ 25812 // C++] Nice Raises (0) | 2022.11.30 |
[BOJ 25761 // C++] 축사 건설 (0) | 2022.11.29 |
[BOJ 25760 // C++] 귀경길 교통상황을 알려드립니다 (0) | 2022.11.28 |
[BOJ 25759 // C++] 들판 건너가기 (0) | 2022.11.27 |