QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#185054 | #5612. Picking Up Steam | ucup-team004 | WA | 0ms | 3908kb | C++20 | 13.0kb | 2023-09-21 16:28:58 | 2023-09-21 16:28:58 |
Judging History
answer
#include <bits/stdc++.h>
using i64 = long long;
template<class T>
struct Point {
T x;
T y;
Point(const T &x_ = 0, const T &y_ = 0) : x(x_), y(y_) {}
template<class U>
operator Point<U>() {
return Point<U>(U(x), U(y));
}
Point &operator+=(const Point &p) & {
x += p.x;
y += p.y;
return *this;
}
Point &operator-=(const Point &p) & {
x -= p.x;
y -= p.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;
}
Point operator-() const {
return Point(-x, -y);
}
friend Point operator+(Point a, const Point &b) {
return a += b;
}
friend Point operator-(Point a, const Point &b) {
return a -= b;
}
friend Point operator*(Point a, const T &b) {
return a *= b;
}
friend Point operator/(Point a, const T &b) {
return a /= b;
}
friend Point operator*(const T &a, Point b) {
return b *= a;
}
friend bool operator==(const Point &a, const Point &b) {
return a.x == b.x && a.y == b.y;
}
friend std::istream &operator>>(std::istream &is, Point &p) {
return is >> p.x >> p.y;
}
friend std::ostream &operator<<(std::ostream &os, const Point &p) {
return os << "(" << p.x << ", " << p.y << ")";
}
};
template<class T>
struct Line {
Point<T> a;
Point<T> b;
Line(const Point<T> &a_ = Point<T>(), const Point<T> &b_ = Point<T>()) : a(a_), b(b_) {}
};
template<class T>
T dot(const Point<T> &a, const Point<T> &b) {
return a.x * b.x + a.y * b.y;
}
template<class T>
T cross(const Point<T> &a, const Point<T> &b) {
return a.x * b.y - a.y * b.x;
}
template<class T>
T square(const Point<T> &p) {
return dot(p, p);
}
template<class T>
double length(const Point<T> &p) {
return std::sqrt(square(p));
}
template<class T>
double length(const Line<T> &l) {
return length(l.a - l.b);
}
template<class T>
Point<T> normalize(const Point<T> &p) {
return p / length(p);
}
template<class T>
double distance(const Point<T> &a, const Point<T> &b) {
return length(a - b);
}
template<class T>
double distancePL(const Point<T> &p, const Line<T> &l) {
return std::abs(cross(l.a - l.b, l.a - p)) / length(l);
}
template<class T>
double distancePS(const Point<T> &p, const Line<T> &l) {
if (dot(p - l.a, l.b - l.a) < 0) {
return distance(p, l.a);
}
if (dot(p - l.b, l.a - l.b) < 0) {
return distance(p, l.b);
}
return distancePL(p, l);
}
template<class T>
Point<T> rotate(const Point<T> &a) {
return Point(-a.y, a.x);
}
template<class T>
int sgn(const Point<T> &a) {
return a.y > 0 || (a.y == 0 && a.x > 0) ? 1 : -1;
}
template<class T>
bool pointOnLineLeft(const Point<T> &p, const Line<T> &l) {
return cross(l.b - l.a, p - l.a) > 0;
}
template<class T>
Point<T> lineIntersection(const Line<T> &l1, const Line<T> &l2) {
return l1.a + (l1.b - l1.a) * (cross(l2.b - l2.a, l1.a - l2.a) / cross(l2.b - l2.a, l1.a - l1.b));
}
template<class T>
bool pointOnSegment(const Point<T> &p, const Line<T> &l) {
return cross(p - l.a, l.b - l.a) == 0 && std::min(l.a.x, l.b.x) <= p.x && p.x <= std::max(l.a.x, l.b.x)
&& std::min(l.a.y, l.b.y) <= p.y && p.y <= std::max(l.a.y, l.b.y);
}
template<class T>
bool pointInPolygon(const Point<T> &a, const std::vector<Point<T>> &p) {
int n = p.size();
for (int i = 0; i < n; i++) {
if (pointOnSegment(a, Line(p[i], p[(i + 1) % n]))) {
return true;
}
}
int t = 0;
for (int i = 0; i < n; i++) {
auto u = p[i];
auto v = p[(i + 1) % n];
if (u.x < a.x && v.x >= a.x && pointOnLineLeft(a, Line(v, u))) {
t ^= 1;
}
if (u.x >= a.x && v.x < a.x && pointOnLineLeft(a, Line(u, v))) {
t ^= 1;
}
}
return t == 1;
}
// 0 : not intersect
// 1 : strictly intersect
// 2 : overlap
// 3 : intersect at endpoint
template<class T>
std::tuple<int, Point<T>, Point<T>> segmentIntersection(const Line<T> &l1, const Line<T> &l2) {
if (std::max(l1.a.x, l1.b.x) < std::min(l2.a.x, l2.b.x)) {
return {0, Point<T>(), Point<T>()};
}
if (std::min(l1.a.x, l1.b.x) > std::max(l2.a.x, l2.b.x)) {
return {0, Point<T>(), Point<T>()};
}
if (std::max(l1.a.y, l1.b.y) < std::min(l2.a.y, l2.b.y)) {
return {0, Point<T>(), Point<T>()};
}
if (std::min(l1.a.y, l1.b.y) > std::max(l2.a.y, l2.b.y)) {
return {0, Point<T>(), Point<T>()};
}
if (cross(l1.b - l1.a, l2.b - l2.a) == 0) {
if (cross(l1.b - l1.a, l2.a - l1.a) != 0) {
return {0, Point<T>(), Point<T>()};
} else {
auto maxx1 = std::max(l1.a.x, l1.b.x);
auto minx1 = std::min(l1.a.x, l1.b.x);
auto maxy1 = std::max(l1.a.y, l1.b.y);
auto miny1 = std::min(l1.a.y, l1.b.y);
auto maxx2 = std::max(l2.a.x, l2.b.x);
auto minx2 = std::min(l2.a.x, l2.b.x);
auto maxy2 = std::max(l2.a.y, l2.b.y);
auto miny2 = std::min(l2.a.y, l2.b.y);
Point<T> p1(std::max(minx1, minx2), std::max(miny1, miny2));
Point<T> p2(std::min(maxx1, maxx2), std::min(maxy1, maxy2));
if (!pointOnSegment(p1, l1)) {
std::swap(p1.y, p2.y);
}
if (p1 == p2) {
return {3, p1, p2};
} else {
return {2, p1, p2};
}
}
}
auto cp1 = cross(l2.a - l1.a, l2.b - l1.a);
auto cp2 = cross(l2.a - l1.b, l2.b - l1.b);
auto cp3 = cross(l1.a - l2.a, l1.b - l2.a);
auto cp4 = cross(l1.a - l2.b, l1.b - l2.b);
if ((cp1 > 0 && cp2 > 0) || (cp1 < 0 && cp2 < 0) || (cp3 > 0 && cp4 > 0) || (cp3 < 0 && cp4 < 0)) {
return {0, Point<T>(), Point<T>()};
}
Point p = lineIntersection(l1, l2);
if (cp1 != 0 && cp2 != 0 && cp3 != 0 && cp4 != 0) {
return {1, p, p};
} else {
return {3, p, p};
}
}
template<class T>
double distanceSS(const Line<T> &l1, const Line<T> &l2) {
if (std::get<0>(segmentIntersection(l1, l2)) != 0) {
return 0.0;
}
return std::min({distancePS(l1.a, l2), distancePS(l1.b, l2), distancePS(l2.a, l1), distancePS(l2.b, l1)});
}
template<class T>
bool segmentInPolygon(const Line<T> &l, const std::vector<Point<T>> &p) {
int n = p.size();
if (!pointInPolygon(l.a, p)) {
return false;
}
if (!pointInPolygon(l.b, p)) {
return false;
}
for (int i = 0; i < n; i++) {
auto u = p[i];
auto v = p[(i + 1) % n];
auto w = p[(i + 2) % n];
auto [t, p1, p2] = segmentIntersection(l, Line(u, v));
if (t == 1) {
return false;
}
if (t == 0) {
continue;
}
if (t == 2) {
if (pointOnSegment(v, l) && v != l.a && v != l.b) {
if (cross(v - u, w - v) > 0) {
return false;
}
}
} else {
if (p1 != u && p1 != v) {
if (pointOnLineLeft(l.a, Line(v, u))
|| pointOnLineLeft(l.b, Line(v, u))) {
return false;
}
} else if (p1 == v) {
if (l.a == v) {
if (pointOnLineLeft(u, l)) {
if (pointOnLineLeft(w, l)
&& pointOnLineLeft(w, Line(u, v))) {
return false;
}
} else {
if (pointOnLineLeft(w, l)
|| pointOnLineLeft(w, Line(u, v))) {
return false;
}
}
} else if (l.b == v) {
if (pointOnLineLeft(u, Line(l.b, l.a))) {
if (pointOnLineLeft(w, Line(l.b, l.a))
&& pointOnLineLeft(w, Line(u, v))) {
return false;
}
} else {
if (pointOnLineLeft(w, Line(l.b, l.a))
|| pointOnLineLeft(w, Line(u, v))) {
return false;
}
}
} else {
if (pointOnLineLeft(u, l)) {
if (pointOnLineLeft(w, Line(l.b, l.a))
|| pointOnLineLeft(w, Line(u, v))) {
return false;
}
} else {
if (pointOnLineLeft(w, l)
|| pointOnLineLeft(w, Line(u, v))) {
return false;
}
}
}
}
}
}
return true;
}
template<class T>
std::vector<Point<T>> hp(std::vector<Line<T>> lines) {
std::sort(lines.begin(), lines.end(), [&](auto l1, auto l2) {
auto d1 = l1.b - l1.a;
auto d2 = l2.b - l2.a;
if (sgn(d1) != sgn(d2)) {
return sgn(d1) == 1;
}
return cross(d1, d2) > 0;
});
std::deque<Line<T>> ls;
std::deque<Point<T>> ps;
for (auto l : lines) {
if (ls.empty()) {
ls.push_back(l);
continue;
}
while (!ps.empty() && !pointOnLineLeft(ps.back(), l)) {
ps.pop_back();
ls.pop_back();
}
while (!ps.empty() && !pointOnLineLeft(ps[0], l)) {
ps.pop_front();
ls.pop_front();
}
if (cross(l.b - l.a, ls.back().b - ls.back().a) == 0) {
if (dot(l.b - l.a, ls.back().b - ls.back().a) > 0) {
if (!pointOnLineLeft(ls.back().a, l)) {
assert(ls.size() == 1);
ls[0] = l;
}
continue;
}
return {};
}
ps.push_back(lineIntersection(ls.back(), l));
ls.push_back(l);
}
while (!ps.empty() && !pointOnLineLeft(ps.back(), ls[0])) {
ps.pop_back();
ls.pop_back();
}
if (ls.size() <= 2) {
return {};
}
ps.push_back(lineIntersection(ls[0], ls.back()));
return std::vector(ps.begin(), ps.end());
}
using real = double;
using P = Point<real>;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<P> a(n + 1);
for (int i = 0; i <= n; i++) {
int x, y;
std::cin >> x >> y;
a[i] = P(x, y);
}
int x0;
std::cin >> x0;
P s, vec;
real r, v;
std::cin >> s.x >> s.y >> r >> vec.x >> vec.y >> v;
int p = 0;
while (a[p + 1].x < x0) {
p++;
}
P o = a[p] + (a[p + 1] - a[p]) / (a[p + 1].x - a[p].x) * (x0 - a[p].x);
P ang;
vec = normalize(vec) * v;
real ans = -1;
constexpr real inf = 1E9;
auto work = [&](P u, P v) {
if (s.x >= u.x && s.x <= v.x && pointOnLineLeft(s, Line(u, v))) {
ans = 0;
return;
}
Line l1(u, P(u.x, inf)), l2(u, v), l3(v, P(v.x, inf));
real lo = 0, hi = 1E5;
auto check = [&](real t) {
Line l(s, s + vec * t);
return distanceSS(l, l1) < r || distanceSS(l, l2) < r || distanceSS(l, l3) < r;
};
if (!check(hi)) {
return;
}
for (int t = 0; t < 100; t++) {
real m = (lo + hi) / 2;
if (check(m)) {
hi = m;
} else {
lo = m;
}
}
if (ans < 0 || ans > lo) {
ans = lo;
}
};
if (a[0].x == x0) {
p--;
}
for (int i = p; i >= 0; i--) {
if (i == p || cross(a[i] - o, ang - o) > 0) {
ang = a[i];
}
P u = o + (ang - o) / (ang.x - o.x) * (a[i].x - o.x);
P v = o + (ang - o) / (ang.x - o.x) * (a[i + 1].x - o.x);
work(u, v);
}
if (a[p + 1].x == x0) {
p++;
}
for (int i = p; i < n; i++) {
if (i == p || cross(a[i + 1] - o, ang - o) < 0) {
ang = a[i + 1];
}
P u = o + (ang - o) / (ang.x - o.x) * (a[i].x - o.x);
P v = o + (ang - o) / (ang.x - o.x) * (a[i + 1].x - o.x);
work(u, v);
}
if (ans < 0) {
std::cout << -1 << "\n";
} else {
std::cout << std::fixed << std::setprecision(10) << ans << "\n";
}
return 0;
}
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 3904kb
input:
7 1 0 2 2 4 2 5 5 6 0 9 4 12 3 14 0 2 13 -1 1 -1 1 1
output:
8.8994949366
result:
ok found '8.89949', expected '8.89900', error '0.00006'
Test #2:
score: 0
Accepted
time: 0ms
memory: 3880kb
input:
3 0 0 3 3 6 3 9 0 3 4 1 1 -1 1 1
output:
1.1213203436
result:
ok found '1.12132', expected '1.12132', error '0.00000'
Test #3:
score: 0
Accepted
time: 0ms
memory: 3772kb
input:
3 0 0 3 3 6 3 9 0 4 4 1 1 -1 1 1
output:
1.4142135624
result:
ok found '1.41421', expected '1.41421', error '0.00000'
Test #4:
score: 0
Accepted
time: 0ms
memory: 3716kb
input:
3 0 0 3 3 6 3 9 0 4 4 1 1 1 1 1
output:
1.4142135624
result:
ok found '1.41421', expected '1.41421', error '0.00000'
Test #5:
score: 0
Accepted
time: 0ms
memory: 3780kb
input:
3 0 0 3 3 6 3 9 0 8 4 1 1 1 1 1
output:
1.8284271247
result:
ok found '1.82843', expected '1.82843', error '0.00000'
Test #6:
score: 0
Accepted
time: 0ms
memory: 3780kb
input:
3 0 0 3 3 6 3 9 0 0 4 1 1 0 1 1
output:
1.5857864376
result:
ok found '1.58579', expected '1.58579', error '0.00000'
Test #7:
score: 0
Accepted
time: 0ms
memory: 3700kb
input:
3 0 0 3 3 6 3 9 0 0 4 1 1 1 1 1
output:
-1
result:
ok found '-1.00000', expected '-1.00000', error '-0.00000'
Test #8:
score: 0
Accepted
time: 0ms
memory: 3784kb
input:
2 10 10 30 40 60 60 50 40 30 10 -1 1 1
output:
3.9440965965
result:
ok found '3.94410', expected '3.94410', error '0.00000'
Test #9:
score: -100
Wrong Answer
time: 0ms
memory: 3908kb
input:
5 0 80 40 0 60 60 100 0 120 40 160 60 0 140 20 20 -1 1 1
output:
8.2842712475
result:
wrong answer 1st numbers differ - expected: '7.20242', found: '8.28427', error = '0.15021'