平面凸包
本题是求凸包周长
#include <bits/stdc++.h> #define rep(i, L, R) for (int i = L; i <= R; ++i) using namespace std; const double eps = 1e-8; const double inf = 1e20; const int N = 107; inline int sgn(double x) { if (fabs(x) < eps) return 0; return x > 0 ? 1 : -1; } struct point { double x, y; point operator+(point b) { return {x + b.x, y + b.y}; }; point operator-(point b) { return {x - b.x, y - b.y}; }; point operator*(double k) { return {x * k, y * k}; }; point operator/(double k) { return {x / k, y / k}; }; bool operator==(point b) { return sgn(x - b.x) == 0 and sgn(y - b.x) == 0; } bool operator<(const point &b) const { return sgn(x - b.x) < 0 || sgn(x - b.x == 0) and sgn(y - b.y) == 0; } }; typedef point pec; double cross(pec a, pec b) { return a.x * b.y - a.y * b.x; } double dis(point a, point b) { return hypot(a.x - b.x, a.y - b.y); } double S(point *a, int n) { //数组起始位置 多边形有多少个点 double res = 0; for (int i = 0; i < n; ++i) res += cross(a[i], a[(i + 1) % n]); return res / 2; // 面积有正负 } int convexHull(point *a, int n, point *res) { sort(a, a + n); n = unique(a, a + n) - a; int p = 0; // 求下凸包 如果点是右拐的 回退 不收纳 for (int i = 0; i < n; ++i) { while (p > 1 and sgn(cross(res[p - 1] - res[p - 2], a[i] - res[p - 2])) <= 0) --p; res[p++] = a[i]; } // 求上凸包 int j = p; for (int i = n - 2; i >= 0; --i) { while (p > j and sgn(cross(res[p - 1] - res[p - 2], a[i] - res[p - 2])) <= 0) --p; res[p++] = a[i]; } if (n > 1) --p; return p; // 凸包顶点数 } point a[N], res[N]; int main() { int n; while (~scanf("%d", &n) && n) { rep(i, 1, n) scanf("%lf%lf", &a[i].x, &a[i].y); int v = convexHull(a + 1, n, res); double ans = 0; if (v == 1) ans = 0; else if (v == 2) ans = dis(res[0], res[1]); else // 凸包周长 for (int i = 0; i < v; ++i) ans += dis(res[i], res[(i + 1) % v]); printf("%.2lf\n", ans); } return 0; }
算法竞赛之路 文章被收录于专栏
整理、记录算法竞赛的好题