QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#633997 | #9455. Getting Lost | ucup-team5062# | WA | 3ms | 4048kb | C++17 | 5.5kb | 2024-10-12 16:32:20 | 2024-10-12 16:32:21 |
Judging History
answer
#include <cmath>
#include <vector>
#include <complex>
#include <iostream>
#include <algorithm>
using namespace std;
const long double INF = 1.0e+99L;
const long double EPS = 1.0e-11L;
const long double PI = acos(-1.0L);
using point = complex<long double>;
double dot(const point& a, const point& b) {
return (conj(a) * b).real();
}
double cross(const point& a, const point& b) {
return (conj(a) * b).imag();
}
point normalize(const point& a) {
return a / abs(a);
}
// distance from point to segment
long double distance(const point& p, const point& s0, const point& s1) {
if (dot(s1 - s0, p - s0) < 0) {
return abs(p - s0);
}
if (dot(s0 - s1, p - s1) < 0) {
return abs(p - s1);
}
return abs(cross(s1 - s0, p - s0)) / abs(s1 - s0);
}
// tangent point between point and circle
vector<point> tangent(const point& p, const point& c, long double r) {
point v = normalize(p - c);
long double d = abs(p - c);
if (d <= r - EPS) {
return vector<point>();
}
if (d <= r + EPS) {
return {p};
}
long double t = r * r / d;
vector<point> res(2);
res[0] = c + (t - point(0, 1) * sqrt(r * r - t * t)) * v;
res[1] = c + (t + point(0, 1) * sqrt(r * r - t * t)) * v;
return res;
}
// tangent point between circle and circle
vector<point> tangent(const point& c0, long double r0, const point& c1, long double r1) {
point v = normalize(c1 - c0);
long double d = abs(c1 - c0);
vector<point> res;
if (d >= r0 + r1 + EPS) {
long double t = r0 * (r0 + r1) / d;
res.push_back(c0 + (t - point(0, 1) * sqrt(r0 * r0 - t * t)) * v);
res.push_back(c0 + (t + point(0, 1) * sqrt(r0 * r0 - t * t)) * v);
} else if (d >= r0 + r1 - EPS) {
long double t = r0 * (r0 + r1) / d;
res.push_back(c0 + t * v);
}
if (d >= abs(r0 - r1) + EPS) {
long double t = r0 * (r0 - r1) / d;
res.push_back(c0 + (t - point(0, 1) * sqrt(r0 * r0 - t * t)) * v);
res.push_back(c0 + (t + point(0, 1) * sqrt(r0 * r0 - t * t)) * v);
} else if (d >= abs(r0 - r1) - EPS) {
long double t = r0 * (r0 - r1) / d;
res.push_back(c0 + t * v);
}
return res;
}
long double solve(int N, const point& A, const point& B, long double D, const vector<point>& P, const vector<double>& R) {
// step #1. enumerate points
vector<point> Q;
Q.push_back(A);
for (int i = 0; i < N; i++) {
vector<point> v = tangent(A, P[i], R[i]);
for (point p : v) {
Q.push_back(p);
}
}
Q.push_back(B);
for (int i = 0; i < N; i++) {
vector<point> v = tangent(B, P[i], R[i]);
for (point p : v) {
Q.push_back(p);
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (i != j) {
vector<point> v = tangent(P[i], R[i], P[j], R[j]);
for (point p : v) {
Q.push_back(p);
}
}
}
}
int Z = Q.size();
for (int i = 0; i < Z; i++) {
if (abs(Q[i] - B) > EPS) {
point v = normalize(Q[i] - B) * D;
bool valid = true;
for (int j = 0; j < N; j++) {
if (abs(P[j] - v) < R[j] - EPS) {
valid = false;
}
}
if (valid) {
Q.push_back(v);
}
}
}
Z = Q.size();
vector<point> true_Q;
for (int i = 0; i < Z; i++) {
bool valid = true;
for (int j = 0; j < i; j++) {
if (abs(Q[i] - Q[j]) < EPS) {
valid = false;
}
}
if (valid) {
true_Q.push_back(Q[i]);
}
}
Q = true_Q;
Z = Q.size();
// step #2. calculate distance table
vector<vector<long double> > d(Z, vector<long double>(Z, 0.0L));
for (int i = 0; i < Z; i++) {
for (int j = i + 1; j < Z; j++) {
bool valid = true;
for (int k = 0; k < N; k++) {
long double d = distance(P[k], Q[i], Q[j]);
if (d < R[k] - EPS) {
valid = false;
}
}
if (valid) {
d[i][j] = abs(Q[i] - Q[j]);
d[j][i] = d[i][j];
} else {
d[i][j] = INF;
d[j][i] = INF;
}
}
}
for (int i = 0; i < N; i++) {
vector<int> g;
for (int j = 0; j < Z; j++) {
if (abs(abs(Q[j] - P[i]) - R[i]) < EPS) {
g.push_back(j);
}
}
for (int j = 0; j < int(g.size()); j++) {
for (int k = j + 1; k < int(g.size()); k++) {
long double arg1 = arg(Q[g[j]] - P[i]);
long double arg2 = arg(Q[g[k]] - P[i]);
long double arg_diff = abs(arg1 - arg2);
arg_diff = min(arg_diff, 2.0L * PI - arg_diff);
d[g[j]][g[k]] = R[i] * arg_diff;
d[g[k]][g[j]] = d[g[j]][g[k]];
}
}
}
// step #3. dijkstra
vector<long double> dist(Z, INF);
dist[0] = 0.0;
vector<bool> used(Z, false);
while (true) {
pair<long double, int> opt = {INF, -1};
for (int j = 0; j < Z; j++) {
if (!used[j]) {
opt = min(opt, {dist[j], j});
}
}
if (opt.first == INF) {
break;
}
int x = opt.second;
used[x] = true;
for (int j = 0; j < Z; j++) {
if (d[x][j] != INF) {
dist[j] = min(dist[j], dist[x] + d[x][j]);
}
}
}
// step #4. compute answer
long double ans = INF;
for (int i = 0; i < Z; i++) {
if (abs(Q[i] - B) < D + EPS) {
ans = min(ans, dist[i]);
}
}
return ans;
}
int main() {
auto input_point = []() -> point {
long double x, y;
cin >> x >> y;
return point(x, y);
};
int T;
cin >> T;
for (int id = 1; id <= T; id++) {
int N;
cin >> N;
point A = input_point();
point B = input_point();
long double D;
cin >> D;
vector<point> P(N); vector<double> R(N);
for (int i = 0; i < N; i++) {
P[i] = input_point();
cin >> R[i];
}
long double ans = solve(N, A, B, D, P, R);
cout.precision(18);
cout << fixed << ans << endl;
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3976kb
input:
2 1 10 0 0 0 2 6 0 1 0 0 10 0 0 5
output:
8.209191463668800912 5.000000000000000000
result:
ok 2 numbers
Test #2:
score: -100
Wrong Answer
time: 3ms
memory: 4048kb
input:
52 0 0 10 0 0 5 0 10 0 0 0 5 1 10 0 0 0 2 6 0 1 1 10 0 4 0 2 6 0 1 1 10 0 3 0 4 6 0 2 1 10 0 3 0 2 6 0 3 1 10 0 3 0 4 6 0 3 2 10 0 -2 0 4 6 4 3 6 -4 3 2 10 0 -2 0 7 6 4 3 6 -4 3 2 10 6 -2 0 7 6 4 3 6 -4 3 2 10 2 -2 0 14 6 4 3 6 -4 3 2 14 4 -2 0 14 6 4 3 6 -4 3 2 12 -10 -2 0 14 2 2 3 6 -4 3 2 8 -8 -2...
output:
5.000000000000000000 5.000000000000000000 8.209191463668800912 4.649262376947794412 5.970754478788285060 9.902326528393723472 9.902326528393723472 12.000000000000000000 6.284809374635578018 8.844014302187676592 0.000000000000000000 5.000000000000000000 7.937253933193771772 0.000000000000000000 0.000...
result:
wrong answer 4th numbers differ - expected: '4.3936128', found: '4.6492624', error = '0.0581866'