QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#451132 | #6831. Known as the Fruit Brother | PetroTarnavskyi# | WA | 1ms | 3956kb | C++20 | 4.7kb | 2024-06-22 21:25:59 | 2024-06-22 21:25:59 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define RFOR(i, a, b) for(int i = (a) - 1; i >= (b); i--)
#define SZ(a) int(a.size())
#define ALL(a) a.begin(), a.end()
#define PB push_back
#define MP make_pair
#define F first
#define S second
typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> PII;
typedef double db;
const db EPS = 1e-9;
const db INF = 1e9;
template<typename T>
void updMin(T& a, T b)
{
a = min(a, b);
}
struct Pt
{
db x, y;
Pt operator+(const Pt& p) const
{
return {x + p.x, y + p.y};
}
Pt operator-(const Pt& p) const
{
return {x - p.x, y - p.y};
}
Pt operator*(db d) const
{
return {x * d, y * d};
}
Pt operator/(db d) const
{
return {x / d, y / d};
}
};
db sq(const Pt& p)
{
return p.x * p.x + p.y * p.y;
}
db abs(const Pt& p)
{
return sqrt(sq(p));
}
int sgn(db x)
{
return (EPS < x) - (x < -EPS);
}
Pt perp(const Pt& p)
{
return {-p.y, p.x};
}
db dot(const Pt& p, const Pt& q)
{
return p.x * q.x + p.y * q.y;
}
db cross(const Pt& p, const Pt& q)
{
return p.x * q.y - p.y * q.x;
}
db orient(const Pt& p, const Pt& q, const Pt& r)
{
return cross(q - p, r - p) / abs(q - p);
}
ostream& operator<<(ostream& os, const Pt& p)
{
return os << "(" << p.x << "," << p.y << ")";
}
struct Line
{
Pt n;
db c;
Line(const Pt& p, const Pt& q):
n(perp(q - p)), c(-dot(n, p)) {}
db side(const Pt& p) const
{
return dot(n, p) + c;
}
db sqDist(const Pt& p) const
{
return side(p) * side(p) / (db)sq(n);
}
Pt proj(const Pt& p) const
{
return p - n * side(p) / sq(n);
}
};
bool inDisk(const Pt& a, const Pt& b, const Pt& p)
{
return sgn(dot(a - p, b - p)) <= 0;
}
bool onSegment(const Pt& a, const Pt& b, const Pt& p)
{
return sgn(orient(a, b, p)) == 0 && inDisk(a, b, p);
}
bool properInter(const Pt& a, const Pt& b, const Pt& c, const Pt& d)
{
db oa = orient(c, d, a);
db ob = orient(c, d, b);
db oc = orient(a, b, c);
db od = orient(a, b, d);
return sgn(oa) * sgn(ob) == -1 && sgn(oc) * sgn(od) == -1;
}
vector<Pt> circleLine(const Pt& o, db r, const Line& l)
{
db h2 = r * r - l.sqDist(o);
if (sgn(h2) == -1)
return {};
Pt p = l.proj(o);
if (sgn(h2) == 0)
return {p};
Pt h = perp(l.n) * sqrt(h2) / abs(l.n);
return {p - h, p + h};
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout << fixed << setprecision(10);
int n, m, r;
cin >> n >> m >> r;
vector<Pt> vertices;
FOR(i, 0, n)
{
db x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
vertices.PB({x1, y1});
vertices.PB({x2, y1});
vertices.PB({x2, y2});
vertices.PB({x1, y2});
}
FOR(i, 0, m)
{
db x, y;
cin >> x >> y;
vertices.PB({x, y});
}
db xs, ys, xt, yt;
cin >> xs >> ys >> xt >> yt;
vertices.PB({xs, ys});
vertices.PB({xt, yt});
int k = SZ(vertices);
vector dist(k, vector<db>(k, INF));
auto check = [&](const Pt& p1, const Pt& p2) -> bool
{
bool ok = true;
FOR(l, 0, n)
{
FOR(p, 0, 4)
{
Pt q1 = vertices[4 * l + p], q2 = vertices[4 * l + (p + 1) % 4];
ok &= !properInter(p1, p2, q1, q2);
}
ok &= !(onSegment(p1, p2, vertices[4 * l]) && onSegment(p1, p2, vertices[4 * l + 2]));
ok &= !(onSegment(p1, p2, vertices[4 * l + 1]) && onSegment(p1, p2, vertices[4 * l + 3]));
}
return ok;
};
auto checkPoint = [&](const Pt& pt) -> bool
{
FOR(l, 0, n)
{
bool inside = true;
FOR(p, 0, 4)
{
Pt q1 = vertices[4 * l + p], q2 = vertices[4 * l + (p + 1) % 4];
inside &= sgn(orient(q1, q2, pt)) >= 0;
}
if (inside)
return false;
}
return true;
};
FOR(i, 0, k)
{
FOR(j, 0, k)
{
if (i == j)
{
dist[i][j] = 0;
continue;
}
Pt p1 = vertices[i], p2 = vertices[j];
bool blast = 4 * n <= i && i < 4 * n + m;
if (check(p1, p2))
{
db d = abs(p2 - p1);
if (blast)
d = max(0.0, d - r);
updMin(dist[i][j], d);
}
if (blast)
{
FOR(l, 0, n)
{
FOR(p, 0, 4)
{
Pt q1 = vertices[4 * l + p], q2 = vertices[4 * l + (p + 1) % 4];
Line q12(q1, q2);
vector<Pt> vec = circleLine(p1, r, q12);
for (const Pt& pt : vec)
{
if (onSegment(q1, q2, pt) && check(pt, p2))
{
updMin(dist[i][j], abs(p2 - pt));
}
}
}
}
if (r < abs(p2 - p1) - EPS)
{
Pt pt = p1 + (p2 - p1) / abs(p2 - p1) * r;
if (check(pt, p2) && checkPoint(pt))
{
updMin(dist[i][j], abs(p2 - pt));
}
}
}
}
}
FOR(kk, 0, k)
FOR(i, 0, k)
FOR(j, 0, k)
updMin(dist[i][j], dist[i][kk] + dist[kk][j]);
cout << dist[k - 2][k - 1] << "\n";
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3956kb
input:
1 2 2 0 2 7 4 -3 3 8 2 1 1 6 6
output:
9.5432037669
result:
ok found '9.5432038', expected '9.5432038', error '0.0000000'
Test #2:
score: 0
Accepted
time: 0ms
memory: 3888kb
input:
1 2 3 0 2 7 4 -1 4 8 2 1 1 6 6
output:
7.9303914292
result:
ok found '7.9303914', expected '7.9303914', error '0.0000000'
Test #3:
score: 0
Accepted
time: 0ms
memory: 3884kb
input:
1 2 2 2 2 7 4 -1 4 8 2 1 1 6 6
output:
7.6344136152
result:
ok found '7.6344136', expected '7.6344136', error '0.0000000'
Test #4:
score: 0
Accepted
time: 0ms
memory: 3892kb
input:
1 2 1 0 2 7 4 -4 4 8 2 1 1 6 6
output:
9.7387688827
result:
ok found '9.7387689', expected '9.7387689', error '0.0000000'
Test #5:
score: 0
Accepted
time: 0ms
memory: 3884kb
input:
1 2 2 0 2 7 5 -4 4 8 2 1 1 6 6
output:
9.6475590344
result:
ok found '9.6475590', expected '9.6475590', error '0.0000000'
Test #6:
score: 0
Accepted
time: 0ms
memory: 3848kb
input:
1 0 114514 0 0 6 2 2 -1 5 3
output:
7.5373191880
result:
ok found '7.5373192', expected '7.5373192', error '0.0000000'
Test #7:
score: -100
Wrong Answer
time: 1ms
memory: 3896kb
input:
5 4 10 1 -99999 9 99999 11 -99999 19 99999 21 -99999 23 99999 -99999 999999 99999 1000000 -99999 -1000000 99999 -999999 0 0 10 0 20 0 24 7 -1 0 30 7
output:
12.1508275257
result:
wrong answer 1st numbers differ - expected: '1.0000000', found: '12.1508275', error = '11.1508275'