[洛谷P3829][SHOI2012]信用卡凸包
题目大意:有$n$张一模一样的信用卡,每个角进行了圆滑处理,问这些卡组成的“凸包”的周长
题解:发现是圆滑处理的圆心围成的凸包加上一个圆周即可
卡点:输入长宽弄反,然后以为是卡精
C++ Code:
#include <algorithm> #include <cstdio> #include <cmath> #include <iomanip> #include <iostream> #define maxn 10010 const double Pi = acosl(-1); struct Point { long double x, y; Point() { } Point(long double __x, long double __y) : x(__x), y(__y) { } inline long double operator ^ (const Point &rhs) const { return x * rhs.y - y * rhs.x; } 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 Point rotate(long double theta) { const long double Sin = sinl(theta), Cos = cosl(theta); return Point(x * Cos - y * Sin, x * Sin + y * Cos); } } s[maxn << 2], O, v[maxn << 2]; inline long double abs2(const Point &x) { return x.x * x.x + x.y * x.y; } inline long double dis(const Point &lhs, const Point &rhs) { return sqrtl(abs2(lhs - rhs)); } inline long double det(const Point &O, const Point &lhs, const Point &rhs) { return (lhs - O) ^ (rhs - O); } inline bool cmp(const Point &x, const Point &y) { static Point X, Y; X = x - O, Y = y - O; static long double tmp; tmp = X ^ Y; return (tmp > 0) || (tmp == 0 && abs2(X) < abs2(Y)); } int n, tot; long double ans, A, B, R; int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> n >> A >> B >> R; ans = 2 * R * Pi; A /= 2, B /= 2, A -= R, B -= R; for (int i = 0; i < n; ++i) { static long double x, y, theta; std::cin >> x >> y >> theta; const Point t1 = Point(B, A).rotate(theta), t2 = Point(B, -A).rotate(theta), O(x, y); s[tot++] = O - t1, s[tot++] = O + t1; s[tot++] = O - t2, s[tot++] = O + t2; } int miny = 0; for (int i = 0; i < tot; ++i) if (s[i].y < s[miny].y || (s[i].y == s[miny].y && s[i].x < s[miny].x)) miny = i; std::swap(s[0], s[miny]); O = s[0]; std::sort(s + 1, s + tot, cmp); n = tot, tot = 3; v[0] = s[0], v[1] = s[1], v[2] = s[2]; for (int i = 3; i < n; ++i) { Point *a = v + tot - 2, *b = v + tot - 1; while (tot > 2 && det(*a, *b, s[i]) <= 0) { --tot, --a, --b; } v[tot++] = s[i]; } for (int i = 1; i < tot; ++i) ans += dis(v[i - 1], v[i]); ans += dis(v[0], v[tot - 1]); std::cout << std::fixed << std::setprecision(2) << ans << '\n'; return 0; }