QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#875039 | #5843. Grazing Google Goats | crimson231 | 32 ✓ | 1351ms | 4736kb | C++23 | 6.5kb | 2025-01-29 00:56:02 | 2025-01-29 00:56:02 |
Judging History
answer
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::vector<int> Vint;
typedef std::vector<ld> Vld;
const ld INF = 1e17;
const ld TOL = 1e-10;
const ld PI = acos(-1);
const int LEN = 1005;
inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
inline bool zero(const ld& x) { return !sign(x); }
inline bool eq(const ld& x, const ld& y) { return zero(x - y); }
inline ll sq(const ll& x) { return x * x; }
inline ld sq(const ld& x) { return x * x; }
inline ld norm(ld th) {
while (th < 0) th += 2 * PI;
while (sign(th - 2 * PI) >= 0) th -= 2 * PI;
return th;
}
int T, N, M;
struct Pos {
ld x, y;
Pos(ld X_ = 0, ld y_ = 0) : x(X_), y(y_) {}
bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
Pos operator * (const ld& n) const { return { x * n, y * n }; }
Pos operator / (const ld& n) const { return { x / n, y / n }; }
ld operator * (const Pos& p) const { return { x * p.x + y * p.y }; }
ld operator / (const Pos& p) const { return { x * p.y - y * p.x }; }
Pos operator ~ () const { return { -y, x }; }
Pos operator ! () const { return { -x, -y }; }
Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
Pos rot(const ld& t) { return { x * cos(t) - y * sin(t), x * sin(t) + y * cos(t) }; }
ld Euc() const { return x * x + y * y; }
ld mag() const { return sqrt(Euc()); }
Pos unit() const { return *this / mag(); }
ld rad() const { return atan2(y, x); }
friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = Pos(0, 0);
typedef std::vector<Pos> Polygon;
ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { return sign(cross(d1, d2, d3)); }
Polygon graham_scan(Polygon C) {
Polygon H;
if (C.size() < 3) {
std::sort(C.begin(), C.end());
return C;
}
std::swap(C[0], *min_element(C.begin(), C.end()));
std::sort(C.begin() + 1, C.end(), [&](const Pos& p, const Pos& q) -> bool {
int ret = ccw(C[0], p, q);
if (!ret) return (C[0] - p).Euc() < (C[0] - q).Euc();
return ret > 0;
}
);
C.erase(unique(C.begin(), C.end()), C.end());
int sz = C.size();
for (int i = 0; i < sz; i++) {
while (H.size() >= 2 && ccw(H[H.size() - 2], H.back(), C[i]) <= 0)
H.pop_back();
H.push_back(C[i]);
}
return H;
}
bool inner_check(const Polygon& H, const Pos& p) {
int sz = H.size();
for (int i = 0; i < sz; i++) if (ccw(H[i], H[(i + 1) % sz], p) < 0) return 0;
return 1;
}
struct Circle {
Pos c;
ld r;
Circle(Pos c_ = Pos(), ld r_ = 0) : c(c_), r(r_) {}
bool operator > (const Pos& p) const { return sign(r - (c - p).mag()) > 0; }
bool outside(const Circle& q) const { return sign((c - q.c).Euc() - sq((ll)r + q.r)) >= 0; }
Pos p(const ld& t) const { return c + Pos(r, 0).rot(t); }
ld rad(const Pos& p) const { return (p - c).rad(); }
ld area(const ld& lo, const ld& hi) const { return (hi - lo) * r * r * .5; }
ld green(const ld& lo, const ld& hi) const {
Pos s = Pos(cos(lo), sin(lo)), e = Pos(cos(hi), sin(hi));
ld fan = area(lo, hi);
Pos m = c + (s + e) * r * (ld).5;
ld tz = (cos(lo) - cos(hi)) * m.y * r;
return fan + tz - (s / e) * r * r * (ld).5;
}
} C[LEN];
typedef std::vector<Circle> Circles;
Vld intersections(const Circle& a, const Circle& b) {
Pos ca = a.c, cb = b.c;
Pos vec = cb - ca;
ld ra = a.r, rb = b.r;
ld distance = vec.mag();
ld rd = vec.rad();
if (vec.Euc() > sq(ra + rb) + TOL) return {};
if (vec.Euc() < sq(ra - rb) - TOL) return {};
ld X = (ra * ra - rb * rb + vec.Euc()) / (2 * distance * ra);
if (X < -1) X = -1;
if (X > 1) X = 1;
ld h = acos(X);
Vld ret = {};
ret.push_back(norm(rd - h));
if (zero(h)) return ret;
ret.push_back(norm(rd + h));
return ret;
}
ld green(const Pos& q, const Pos& p0, const Pos& p1, const Pos& p2) {
Circle c0 = Circle(p0, (p0 - q).mag());
Circle c1 = Circle(p1, (p1 - q).mag());
Circle c2 = Circle(p2, (p2 - q).mag());
ld a = 0;
Vld V = { 0, 2 * PI };
Vld i10 = intersections(c1, c0);
Vld i12 = intersections(c1, c2);
for (const ld& x : i10) V.push_back(x);
for (const ld& x : i12) V.push_back(x);
std::sort(V.begin(), V.end());
int sz = V.size();
for (int i = 0; i < sz - 1; i++) {
const ld& s = V[i], & e = V[i + 1];
ld m = (s + e) * .5;
Pos mid = c1.p(m);
if (c0 > mid && c2 > mid) a += c1.green(s, e);
}
return a;
}
ld A[LEN];
void query(const int& t) {
std::cin >> N >> M;
Polygon P(N); for (Pos& p : P) std::cin >> p;
Polygon Q(M); for (Pos& p : Q) std::cin >> p;
memset(A, 0, sizeof A);
for (int j = 0; j < M; j++) {
const Pos& q = Q[j];
Polygon R = P;
for (Pos& p : R) p -= q;
Polygon H = graham_scan(R);
if (inner_check(H, O)) { A[j] = 0; continue; }
std::sort(R.begin(), R.end(), [&](const Pos& p, const Pos& q) -> bool {
int tq = sign(p / q);
return !tq ? p.Euc() < q.Euc() : tq > 0;
});
Polygon S;
for (int i = 0; i < N; i++) {
while (S.size() > 1 && ccw(S[S.size() - 2], S[S.size() - 1], R[i]) > 0)
S.pop_back();
S.push_back(R[i]);
}
int sz = S.size();
for (int i = 0; i < sz; i++) {
A[j] += green(O, S[(i - 1 + sz) % sz], S[i], S[(i + 1) % sz]);
}
}
std::cout << "Case #" << t << ": ";
for (int j = 0; j < M; j++) std::cout << A[j] << " ";
std::cout << "\n";
return;
}
void solve() {
std::cin.tie(0)->sync_with_stdio(0);
std::cout.tie(0);
std::cout << std::fixed;
std::cout.precision(9);
std::cin >> T;
for (int t = 1; t <= T; t++) query(t);
}
int main() { solve(); return 0; }//boj12570 Grazing Google Goats (Large)
Details
Tip: Click on the bar to expand more detailed information
Subtask #1:
score: 7
Accepted
Test #1:
score: 7
Accepted
time: 0ms
memory: 4352kb
input:
100 2 3 0 20 20 0 -20 10 40 20 0 19 2 2 5000 5000 -5000 -5000 0 1 9999 10000 2 2 -3991 3294 3522 5116 -2474 -8624 -5079 5997 2 3 6008 -284 -3406 -333 -9568 4461 -6460 5311 -5717 -8348 2 7 250 -205 7085 6339 7877 -4694 -6198 -1353 5241 8985 8083 7531 -9254 1039 5249 774 -3015 6214 2 8 -7255 3388 -579...
output:
Case #1: 1264.986591056 1713.274122872 0.293944048 Case #2: 0.000066672 157048219.894524157 Case #3: 357566591.180694580 17690634.084072094 Case #4: 185217030.645468533 111364766.822879925 174799791.349080950 Case #5: 128408445.597818792 131460516.412476659 21660894.322313987 7590971.345003801 2...
result:
ok correct! (100 test cases)
Subtask #2:
score: 25
Accepted
Test #2:
score: 25
Accepted
time: 1351ms
memory: 4736kb
input:
10 4 2 0 0 100 100 300 0 380 90 400 100 1000 5 3 1 0 0 10 10 20 0 10 5 5000 1000 2711 1967 -5540 -2569 6973 -6302 503 -6330 43 4060 740 -5327 -6234 -3920 -4266 -6846 -3452 7043 7003 4762 3846 3157 3486 6570 -3058 6398 2888 7022 -4162 -6780 2196 7419 -2651 5558 6756 4156 4834 -3179 -7112 -242 1439 -2...
output:
Case #1: 1518.906372852 1193932.969220557 Case #2: 0.000000000 Case #3: 73413.202044869 0.000000000 0.000000000 410358.500822138 2029149.235377457 958781.452600828 0.000000000 6239052.938113177 30459.261112236 7405725.950004961 3388181.775726997 0.000000000 1065026.280991348 2523320.912381392 0.00...
result:
ok correct! (10 test cases)
Extra Test:
score: 0
Extra Test Passed