QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#633936#9455. Getting Lostucup-team5062#WA 4ms4080kbC++175.4kb2024-10-12 16:26:562024-10-12 16:26:56

Judging History

你现在查看的是最新测评结果

  • [2024-10-12 16:26:56]
  • 评测
  • 测评结果:WA
  • 用时:4ms
  • 内存:4080kb
  • [2024-10-12 16:26:56]
  • 提交

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 = i + 1; j < N; 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: 0ms
memory: 3960kb

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: 4ms
memory: 4080kb

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'