QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#813679 | #7027. Machining Disc Rotors | yangjl | AC ✓ | 175ms | 3916kb | C++20 | 14.4kb | 2024-12-14 11:44:46 | 2024-12-14 11:44:47 |
Judging History
answer
/**
* author: yangjl
* created: 2024.12.14 11:26:07
**/
#include <bits/stdc++.h>
#ifdef YJL
#include "debug.h"
#else
#define debug(...)0
#endif
using namespace std;
using ll = long long;
template<class T>
istream& operator>>(istream& is, vector<T>& v) {
for(auto& x : v) {
is >> x;
}
return is;
}
template<class T>
int sgn(const T& v) {
static constexpr T eps = 1e-8;
return v > eps ? 1 : v < -eps ? -1 : 0;
}
template<class T>
struct Point {// Point or Vector
T x, y;
Point() : x(0), y(0) {}
Point(T x, T y) : x(x), y(y) {}
template<class U>
explicit operator Point<U>() const {
return Point<U>(U(x), U(y));
}
Point operator+(const Point& o) const {
return Point(x + o.x, y + o.y);
}
Point operator-(const Point& o) const {
return Point(x - o.x, y - o.y);
}
Point operator-() const {
return Point(-x, -y);
}
Point operator*(const T& v) const {
return Point(x * v, y * v);
}
friend Point operator*(const T& v, const Point<T>& o) {
return Point(o.x * v, o.y * v);
}
Point operator/(const T& v) const {
return Point(x / v, y / v);
}
Point operator+=(const Point& o) {
x += o.x, y += o.y;
return *this;
}
Point operator-=(const Point& o) {
x -= o.x, y -= o.y;
return *this;
}
Point operator*=(const T& v) {
x *= v, y *= v;
return *this;
}
Point operator/=(const T& v) {
x /= v, y /= v;
return *this;
}
bool operator==(const Point& o) const {
return sgn(x - o.x) == 0 and sgn(y - o.y) == 0;
}
bool operator!=(const Point& o) const {
return sgn(x - o.x) != 0 or sgn(y - o.y) != 0;
}
bool operator<(const Point& o) const {
return sgn(x - o.x) < 0 or sgn(x - o.x) == 0 and sgn(y - o.y) < 0;
}
bool operator>(const Point& o) const {
return sgn(x - o.x) > 0 or sgn(x - o.x) == 0 and sgn(y - o.y) > 0;
}
static bool argcmp(const Point& a, const Point& b) {
static auto get = [&](const Point& o) {
if(sgn(o.x) == 0 and sgn(o.y) == 0) return 0;
if(sgn(o.y) > 0 or sgn(o.y) == 0 and sgn(o.x) < 0) return 1;
return -1;
};
int ta = get(a), tb = get(b);
if(ta != tb) return ta < tb;
return a.toLeft(b) == 1;// 不关注极径
// int tole = a.toLeft(b);
// if(tole != 0) return tole == 1;
// return sgn(a.square()-b.square()) < 0;// 极角相同按极径排
}
T dot(const Point& o) const {
return x * o.x + y * o.y;
}
T cross(const Point& o) const {
return x * o.y - y * o.x;
}
int toLeft(const Point& o) const {
return sgn(cross(o));
}
T square() const {
return x * x + y * y;
}
T interSquare(const Point& o) const {
return (*this - o).square();
}
friend istream& operator>>(istream& in, Point& o) {
return in >> o.x >> o.y;
}
friend ostream& operator<<(ostream& out, Point const& o) {
return out << "(" << o.x << "," << o.y << ")";
}
// 涉及浮点数
double length() const {
return sqrtl(square());
}
double distance(const Point& o) const {
return (*this - o).length();
}
// 逆时针旋转 rad, rotate90(0, 1);
Point<T> rotate(T cosr, T sinr) const {
return Point(x * cosr - y * sinr, x * sinr + y * cosr);
}
// 两向量夹角范围是 [0,PI]
double ang(const Point& o) const {
return acosl(max<double>(-1.L, min<double>(1.L, dot(o) / (length() * o.length()))));
}
};
template<class T>
struct Line {// 直线,线段,射线
Point<T> a, b;// 方向为 a->b
Line() {}
Line(const Point<T>& a, const Point<T>& b) : a(a), b(b) {}
template<class U>
Line(const Point<U>& a, const Point<U>& b) : a(a), b(b) {}
Point<T> vec() const {
return b - a;
}
// Line ----------------------------------------------------------
bool parallel(const Line& l) const {
return sgn((b - a).cross(l.b - l.a)) == 0;
}
int toLeft(const Point<T>& o) const {
return (b - a).toLeft(o - a);
}
// 涉及浮点数
// 直线交点
Point<double> lineIntersection(const Line& l) const {
return Point<double>(a) + Point<double>(b - a) *
(1. * (l.b - l.a).cross(a - l.a) / (l.b - l.a).cross(a - b));
}
// 点到直线的距离
double distanceLP(const Point<T>& o) const {
return abs((a - b).cross(a - o)) / (a - b).length();
}
// 点在直线上的投影
Point<double> projection(const Point<T>& o) const {
auto t = 1.L * vec().dot(o - a) / vec().square();
return Point<double>(a) + Point<double>(vec()) * t;
}
// -1 点在线段端点 | 0 点不在线段上 | 1 点严格在线段上
int contain(const Point<T>& o) const {
if(o == a or o == b) return -1;
return (o - a).toLeft(o - b) == 0 and sgn((o - a).dot(o - b)) < 0;
}
// 判断线段 vs 直线
// 0 不相交 | 1 严格相交 | 2 仅在某一线段端点处相交 | 3 直线包含线段
int segmentCrossLine(const Line& l) const {
int num = !l.toLeft(a) + !l.toLeft(b);
if(num) return num + 1;
return l.toLeft(a) != l.toLeft(b);
}
// 判断线段 vs 线段
// 0 不相交 | 1 严格相交 | 2 仅在某一线段端点处相交 | 3 两线段有重叠
int segmentCrossSegment(Line s) const {
if((a < b) != (s.a < s.b))
swap(s.a, s.b);
int num = (contain(s.a) != 0) + (contain(s.b) != 0)
+ (s.contain(a) != 0) + (s.contain(b) != 0);
if(parallel(s)) {
if(!num) return 0;
if(b == s.a or a == s.b) return 2;// -.-
return 3;
}
if(num) return 2;
return toLeft(s.a) * toLeft(s.b) == -1 and s.toLeft(a) * s.toLeft(b) == -1;
}
// 射线 vs 线段 判断相交
// 0 不相交 | 1 严格相交 | 2 某个端点相交
int raysCrossSegment(Line const& seg) const {
if(seg.contain(a)) return 2;
if(toLeft(seg.a) == 0 and vec().dot(seg.a - a) > 0) return 2;
if(toLeft(seg.b) == 0 and vec().dot(seg.b - a) > 0) return 2;
return toLeft(seg.a) != toLeft(seg.b) and seg.toLeft(a) != seg.vec().toLeft(vec());
}
// 点到线段的距离
double distanceSP(const Point<T>& o) const {
if(sgn((o - a).dot(b - a)) < 0) return o.distance(a);
if(sgn((o - b).dot(a - b)) < 0) return o.distance(b);
return abs((a - b).cross(a - o)) / (a - b).length();
}
// 两线段间距离
double distanceSS(const Line& s) const {
if(segmentCrossSegment(s)) return 0;
return min({distanceSP(s.a),distanceSP(s.b),
s.distanceSP(a),s.distanceSP(b)});
}
// 直线向左/右偏移 r 的距离
Line<T> offset(int tolef, T r) {
Point<T> v(vec().rotate(0, tolef == 1 ? 1 : -1));
v = v * r / v.length();
return Line<T>(a + v, b + v);
}
};
constexpr double PI = 3.1415926535897932384L;
// using D = double;
template<class D>
struct Circle {
Point<D> c;
D r;
Circle() : c(), r() {}
Circle(Point<D> const& _c, D _r) : c(_c), r(_r) {}
Circle(D _x, D _y, D _r) : c(_x, _y), r(_r) {}
bool operator==(Circle const& cir) const {
return c == cir.c && sgn(r - cir.r) == 0;
}
double perimeter() const {// 周长
return 2 * PI * r;
}
double area() const {// 面积
return PI * r * r;
}
// -1 圆内 | 0 圆上 | 1 圆外
template<class I>
int relation(Point<I> const& p) const {
return sgn(c.interSquare(p) - r * r);
}
// -1 相交 | 0 相切 | 1 相离
template<class I>
int relation(Line<I> const& l) const {
if constexpr(!is_same_v<D, double> && !is_same_v<I, double>) {// x,y int <=1e9
__int128_t t = l.vec().cross(c - l.a);
return sgn(t * t - (__int128_t)r * r * l.vec().square());
}
return sgn(l.distanceLP(c) - r);
}
// 0 相同 | 1 相交 | 2 外切 | 3 相离 | 4 内含 | 5 内切
int relation(Circle const& cir) const {
if(*this == cir) return 0;
auto squre = c.interSquare(cir.c), sr = r + cir.r, dr = abs(r - cir.r);
if(sgn(squre - sr * sr) > 0) return 3;
if(sgn(squre - sr * sr) == 0) return 2;
if(sgn(squre - dr * dr) < 0) return 4;
if(sgn(squre - dr * dr) == 0) return 5;
return 1;
}
friend istream& operator>>(istream& in, Circle& cir) {
return in >> cir.c >> cir.r;
}
friend ostream& operator<<(ostream& out, Circle const& cir) {
return out << "(" << cir.c.x << "," << cir.c.y << "," << cir.r << ")";
}
// 涉及浮点数
vector<Point<double>> intersection(Line<double> const& l) const {
Point<double> cp = l.projection(c);
int t = relation(l);
if(t == 1) return {};
if(t == 0) return {cp};
double d = l.distanceLP(c);
double k = sqrtl(r * r - d * d);
Point<double> e = l.vec() / l.vec().length();
return {cp - e * k, cp + e * k};
}
vector<Point<double>> intersection(Circle const& cir) const {
int re = relation(cir);
assert(re != 0);// 相同,无数个交点
if(re == 3 || re == 4) return {};
Point<double> v = (cir.c - c) / c.distance(cir.c) * r;
if(re == 2) return {c + v};
if(re == 5) return {c + v * (r > cir.r ? 1.L : -1.L)};
auto d2 = c.interSquare(cir.c);
double cosa = (r * r + d2 - cir.r * cir.r) / (2.L * r * sqrtl(d2));
double sina = sqrtl(1 - cosa * cosa);
return {c + v.rotate(cosa, -sina), c + v.rotate(cosa, sina)};
}
double bowArea(Point<double> const& s, Point<double> const& t) const {// s->t弓形面积
double cros = (t - s).cross(c - s);
if(sgn(cros) < 0) return area() - bowArea(t, s);
return (s.ang(t) / PI * area() - cros) / 2;
}
double crossArea(Circle const& cir) const {// 圆与圆交集
int re = relation(cir);
if(re == 2 || re == 3) return 0;
if(re != 1) return min(area(), cir.area());
auto cs = intersection(cir);
return bowArea(cs[1], cs[0]) + cir.bowArea(cs[0], cs[1]);
}
vector<Line<D>> tangentLine(Point<D> const& p) const {
int re = relation(p);
if(re == -1) return {};
if(re == 0) return {Line<double>(p, p + (p - c).rotate(0, 1))};
double d = c.distance(p), cosa = r / d, sina = sqrtl(1 - cosa * cosa);
Point<double> v = (p - c) / d * r;
return {Line(p, c + v.rotate(cosa, sina)), Line(p, c + v.rotate(cosa, -sina))};
}
vector<Line<double>> commonTangentLine(Circle const& cir) const {
int re = relation(cir);
assert(re != 0);// 相同,无数公切线
if(re == 4) return {};
vector<Line<double>> lines;
if(re == 2 || re == 5) {
Point<double> p = intersection(cir)[0];
lines.emplace_back(p, p + (c - cir.c).rotate(0, 1));
}
double d = c.distance(cir.c);
Point<double> e = (cir.c - c) / d;
if(re == 1 || re == 2) {
double cosa = (r - cir.r) / d, sina = sqrtl(1 - cosa * cosa);
Point<double> e1 = e.rotate(cosa, -sina), e2 = e.rotate(cosa, sina);
lines.emplace_back(c + e1 * r, c + e2 * r);
lines.emplace_back(cir.c + e1 * cir.r, cir.c + e2 * cir.r);
}
if(re == 3) {
double cosa = (r + cir.r) / d, sina = sqrtl(1 - cosa * cosa);
Point<double> e1 = e.rotate(cosa, -sina), e2 = e.rotate(cosa, sina);
lines.emplace_back(c + e1 * r, c + e2 * r);
lines.emplace_back(cir.c - e1 * cir.r, cir.c - e2 * cir.r);
}
return lines;
}
tuple<int, Circle, Line<double>> inverse(Line<double> const& l) const {
int t = l.toLeft(c);
if(t == 0) return make_tuple(1, Circle(), l);
Point<double> v = l.vec().rotate(0, (t == 1 ? -1 : 1));
double d = r * r / l.distanceLP(c);
return make_tuple(0, Circle(c + v / v.length() * d / 2, d / 2), Line<double>());
}
tuple<int, Circle, Line<double>> inverse(Circle const& cir) const {
double d = cir.c.distance(c);
Point<double> e = (cir.c - c) / d;
if(cir.relation(c) == 0) {
double d = r * r / (2 * cir.r);
Point<double> p = c + e * d;
return make_tuple(1, Circle(), Line<double>(p, p + e.rotate(0, 1)));
}
if(c == cir.c) return make_tuple(0, Circle(c, r * r / cir.r, Line<double>()));
Point<double> p = c + (r * r / (d - cir.r)) * e;
Point<double> q = c + (r * r / (d + cir.r)) * e;
return make_tuple(0, Circle((p + q) / 2, p.distance(q) / 2), Line<double>());
}
};
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cout << fixed << setprecision(15);
int tt;
cin >> tt;
for(int casei = 1; casei <= tt; ++casei) {
int n, R;
cin >> n >> R;
Circle<double> mainC(0, 0, R);
vector<Circle<double>> cirs;
vector<Point<double>> cros, ps;
for(int i = 0; i < n; ++i) {
Circle<double> c;
cin >> c;
int re = mainC.relation(c);
if(re == 1) {
cirs.emplace_back(c);
auto cs = mainC.intersection(c);
cros.insert(cros.end(), cs.begin(), cs.end());
}
}
auto isNotCover = [&](Point<double> p) {
for(auto& cir : cirs) {
if(cir.relation(p) == -1) {
return false;
}
}
return true;
};
for(auto& p : cros) {
if(isNotCover(p)) {
ps.emplace_back(p);
}
}
n = ps.size();
double d = 0;
for(int i = 0; i < n; ++i) {
if(isNotCover(mainC.c * 2 - ps[i])) {
d = 2 * R;
break;
}
for(int j = i + 1; j < n; ++j) {
d = max(d, ps[i].distance(ps[j]));
}
}
cout << "Case #" << casei << ": " << d << "\n";
}
return 0;
}
/*
*/
这程序好像有点Bug,我给组数据试试?
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 3820kb
input:
1 3 10 0 12 10 11 -6 10 -11 -6 10
output:
Case #1: 18.611654895000253
result:
ok 1 cases
Test #2:
score: 0
Accepted
time: 66ms
memory: 3916kb
input:
5000 3 1000 750 500 625 -250 -625 625 -1000 1000 1000 3 8 -6 -4 5 2 5 5 8 -8 8 1 710 426 -568 994 1 10 -8 6 15 14 931 622 -651 207 -930 438 552 931 890 743 -264 -923 671 889 -315 179 15 761 173 -440 883 81 -938 -310 170 -271 981 91 918 -88 47 136 927 26 903 29 61 -162 936 22 917 129 18 32 595 431 11...
output:
Case #1: 1998.628237512162968 Case #2: 15.989025900097303 Case #3: 1420.000000000000000 Case #4: 19.843134832984433 Case #5: 1862.000000000000000 Case #6: 1190.000000000000000 Case #7: 934.000000000000000 Case #8: 542.000000000000000 Case #9: 1808.000000000000000 Case #10: 1472.000000000000000 Case ...
result:
ok 5000 cases
Test #3:
score: 0
Accepted
time: 175ms
memory: 3916kb
input:
5000 48 527 -419 -335 761 519 85 1 -47 524 3 301 431 2 489 -193 3 -102 516 2 -69 521 2 526 2 3 68 522 3 507 139 1 490 191 1 514 109 2 388 355 2 203 485 2 -127 510 3 42 524 1 323 414 1 11 526 1 -17 526 3 452 269 3 514 -111 3 94 517 1 525 -27 1 347 396 1 480 215 3 275 447 2 150 504 3 226 475 1 465 -24...
output:
Case #1: 1053.694800690881038 Case #2: 1269.660021675118514 Case #3: 1143.844334818409834 Case #4: 1183.562268928594449 Case #5: 1304.000000000000000 Case #6: 1173.961249922394927 Case #7: 1051.608339700099577 Case #8: 1027.719369369270680 Case #9: 1314.000000000000000 Case #10: 1007.717091814115065...
result:
ok 5000 cases