[洛谷P2742]【模板】二维凸包([USACO5.1]圈奶牛Fencing the Cows)
题目大意:求一个点集凸包边长
题解:求凸包,直接求
卡点:发现在较后面数位上有较小的误差,还以为是浮点数误差,最后发现是构造函数写成了$int$类型
C++ Code:
#include <algorithm> #include <cstdio> #include <cmath> #include <iostream> #include <iomanip> #define maxn 10010 inline double sqr(double x) { return x * x; } struct Point { double x, y; Point() { } Point(double __x, double __y) : x(__x), y(__y) { } inline Point operator - (const Point &rhs) const { return Point(x - rhs.x, y - rhs.y); } inline Point operator + (const Point &rhs) const { return Point(x + rhs.x, y + rhs.y); } inline double operator * (const Point &rhs) const { return x * rhs.y - y * rhs.x; } } O, s[maxn], v[maxn]; inline double abs2(const Point &x) { return sqr(x.x) + sqr(x.y); } inline double dis(const Point &lhs, const Point &rhs) { return sqrt(abs2(rhs - lhs)); } inline double det(const Point &O, const Point &lhs, const Point &rhs) { return (lhs - O) * (rhs - O); } inline bool operator < (const Point &lhs, const Point &rhs) { static Point X, Y; X = lhs - O, Y = rhs - O; static double t; t = X * Y; return (t > 0) || (t == 0 && abs2(X) > abs2(Y)); } int n, tot; int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> n; if (n <= 1) { std::cout << "0\n"; return 0; } int miny = 0; for (int i = 0; i < n; ++i) { std::cin >> s[i].x >> s[i].y; if ((s[i].y < s[miny].y) || (s[i].y == s[miny].y && s[i].x < s[miny].x)) miny = i; } if (n == 2) { std::cout << std::fixed << std::setprecision(2) << dis(s[0], s[1]) * 2 << '\n'; return 0; } O = s[miny]; std::swap(s[0], s[miny]); std::sort(s + 1, s + n); v[0] = s[0], v[1] = s[1], v[2] = s[2], tot = 3; for (int i = 3; i < n; ++i) { for (Point a = v[tot - 2], b = v[tot - 1]; tot > 2 && det(a, b, s[i]) <= 0; a = v[tot - 2], b = v[tot - 1]) --tot; v[tot++] = s[i]; } double ans = 0; for (int i = 0, nxt = 0; i < tot; ++i) { nxt += 1 - tot; nxt += nxt >> 31 & tot; ans += dis(v[i], v[nxt]); } std::cout << std::fixed << std::setprecision(2) << ans << '\n'; return 0; }