264 lines
5.6 KiB
C++
264 lines
5.6 KiB
C++
/* Problem URL: https://codeforces.com/gym/104871/problem/G */
|
|
|
|
#include <bits/stdc++.h>
|
|
#include <ext/pb_ds/assoc_container.hpp>
|
|
#include <ext/pb_ds/tree_policy.hpp>
|
|
|
|
using namespace std;
|
|
using namespace __gnu_pbds;
|
|
|
|
template <class T, class comp = less<>>
|
|
using ordered_set = tree<T, null_type , comp , rb_tree_tag , tree_order_statistics_node_update>;
|
|
|
|
#define V vector
|
|
|
|
#define rmin(a, b) a = min(a, b)
|
|
#define rmax(a, b) a = max(a, b)
|
|
|
|
#define rep(i, lim) for (int i = 0; i < (lim); i++)
|
|
#define nrep(i, s, lim) for (int i = s; i < (lim); i++)
|
|
|
|
#define repv(i, v) for (auto &i : (v))
|
|
#define fillv(v) for (auto &itr_ : (v)) { cin >> itr_; }
|
|
#define sortv(v) sort(v.begin(), v.end())
|
|
#define all(v) (v).begin(), (v).end()
|
|
|
|
using vi = vector<int>;
|
|
using vvi = vector<vi>;
|
|
using vvvi = vector<vvi>;
|
|
using vvvvi = vector<vvvi>;
|
|
|
|
using ll = long long;
|
|
|
|
using vl = vector<ll>;
|
|
using vvl = vector<vl>;
|
|
using vvvl = vector<vvl>;
|
|
using vvvvl = vector<vvvl>;
|
|
|
|
template<class v>
|
|
auto operator<<(ostream &os, const vector<v> &vec)->ostream& {
|
|
os << vec[0];
|
|
for (size_t i = 1; i < vec.size(); i++) {
|
|
os << ' ' << vec[i];
|
|
}
|
|
os << '\n';
|
|
return os;
|
|
}
|
|
|
|
template<class v>
|
|
auto operator>>(istream &is, vector<v> &vec)->istream& {
|
|
for (auto &i : vec) {
|
|
is >> i;
|
|
}
|
|
return is;
|
|
}
|
|
|
|
template<class v>
|
|
auto operator<<(ostream &os, const vector<vector<v>> &vec)->ostream& {
|
|
for (auto &i : vec) {
|
|
os << i[0];
|
|
for (size_t j = 1; j < i.size(); j++) {
|
|
os << ' ' << i[j];
|
|
}
|
|
os << '\n';
|
|
}
|
|
return os;
|
|
}
|
|
|
|
template<class v>
|
|
auto operator>>(istream &is, vector<vector<v>> &vec)->istream& {
|
|
for (auto &i : vec) {
|
|
for (auto &j : i) {
|
|
is >> j;
|
|
}
|
|
}
|
|
return is;
|
|
}
|
|
|
|
using ld = long double;
|
|
|
|
ld EPS = 1e-16L;
|
|
|
|
bool eq(ld a, ld b) {
|
|
return abs(a - b) <= EPS;
|
|
}
|
|
|
|
struct pt {
|
|
ld x, y;
|
|
pt(ld x = 0, ld y = 0): x(x), y(y) {}
|
|
|
|
ld operator^(const pt p) const {
|
|
return x*p.y - y*p.x;
|
|
}
|
|
|
|
pt operator-(const pt p) const {
|
|
return {x - p.x, y - p.y};
|
|
}
|
|
|
|
ld operator*(const pt p) const {
|
|
return x*p.x + y*p.y;
|
|
}
|
|
|
|
friend istream& operator >> (istream& in, pt &p) {
|
|
return in >> p.x >> p.y;
|
|
}
|
|
};
|
|
|
|
ld dist(pt p, pt q)
|
|
{
|
|
return hypot(p.y - q.y, p.x - q.x);
|
|
}
|
|
|
|
ld sarea(pt p, pt q, pt r)
|
|
{
|
|
return ((q-p)^(r-q)) / 2;
|
|
}
|
|
|
|
struct line {
|
|
pt p, q;
|
|
line() {}
|
|
line (pt p, pt q): p(p), q(q) {}
|
|
};
|
|
|
|
bool ccw(pt p, pt q, pt r)
|
|
{
|
|
return sarea(p, q, r) > EPS;
|
|
}
|
|
|
|
ld disttoline(pt p, line r)
|
|
{
|
|
return 2 * abs(sarea(p, r.p, r.q)) / dist(r.p, r.q);
|
|
}
|
|
|
|
bool isinseg(pt p, line r)
|
|
{
|
|
pt a = r.p - p, b = r.q - p;
|
|
return eq((a^b), 0) and (a * b) < EPS;
|
|
}
|
|
|
|
bool interseg(line r, line s)
|
|
{
|
|
if (isinseg(r.p, s) or isinseg(r.q, s) or isinseg(s.p, r) or isinseg(s.q, r)) {
|
|
return true;
|
|
}
|
|
|
|
return ccw(r.p, r.q, s.p) != ccw(r.p, r.q, s.q) and ccw(s.p, s.q, r.p) != ccw(s.p, s.q, r.q);
|
|
}
|
|
|
|
ld disttoseg(pt p, line r)
|
|
{
|
|
if ((r.q - r.p) * (p - r.p) < 0) {
|
|
return dist(r.p, p);
|
|
}
|
|
|
|
if ((r.p - r.q) * (p - r.q) < 0) {
|
|
return dist(r.q, p);
|
|
}
|
|
|
|
return disttoline(p, r);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
ios::sync_with_stdio(false);
|
|
cin.tie(nullptr);
|
|
|
|
int t;
|
|
cin >> t;
|
|
while (t--) {
|
|
pt a, b;
|
|
pt cir;
|
|
ld r;
|
|
cin >> a >> b >> cir >> r;
|
|
|
|
if (eq(a.x, b.x) && eq(a.y, b.y)) {
|
|
ld dista = dist(a, cir);
|
|
|
|
if (dista <= r) {
|
|
cout << "0\n";
|
|
continue;
|
|
}
|
|
|
|
dista -= r;
|
|
cout << setprecision(12) << (dista - r) * 2 << '\n';
|
|
continue;
|
|
}
|
|
|
|
ld distret = disttoseg(cir, line(a, b));
|
|
cout << distret << '\n';
|
|
if (distret <= r) {
|
|
cout << setprecision(12) << dist(a, b) << '\n';
|
|
continue;
|
|
}
|
|
|
|
a.x -= cir.x;
|
|
a.y -= cir.y;
|
|
b.x -= cir.x;
|
|
b.y -= cir.y;
|
|
|
|
ld low = -r;
|
|
ld high = r;
|
|
ld ans = 1e18;
|
|
ld eps = 1e-9;
|
|
while (high - low >= eps) {
|
|
ld third = (high - low) / 3;
|
|
ld mid1 = low + third;
|
|
ld mid2 = high - third;
|
|
|
|
auto getans = [&](ld mid) {
|
|
ld one = (a.x - mid);
|
|
ld two = (a.y - sqrt(r * r - mid * mid));
|
|
ld ac = sqrt(one * one + two * two);
|
|
one = (b.x - mid);
|
|
two = (b.y - sqrt(r * r - mid * mid));
|
|
ac += sqrt(one * one + two * two);
|
|
return ac;
|
|
};
|
|
|
|
ld ans1 = getans(mid1);
|
|
ld ans2 = getans(mid2);
|
|
|
|
if (ans1 <= ans2) {
|
|
high = mid2;
|
|
ans = ans1;
|
|
continue;
|
|
}
|
|
|
|
low = mid1;
|
|
ans = ans2;
|
|
}
|
|
|
|
low = -r;
|
|
high = r;
|
|
while (high - low >= eps) {
|
|
ld third = (high - low) / 3;
|
|
ld mid1 = low + third;
|
|
ld mid2 = high - third;
|
|
|
|
auto getans = [&](ld mid) {
|
|
ld one = (a.x - mid);
|
|
ld two = (a.y + sqrt(r * r - mid * mid));
|
|
ld ac = sqrt(one * one + two * two);
|
|
one = (b.x - mid);
|
|
two = (b.y + sqrt(r * r - mid * mid));
|
|
ac += sqrt(one * one + two * two);
|
|
return ac;
|
|
};
|
|
|
|
ld ans1 = getans(mid1);
|
|
ld ans2 = getans(mid2);
|
|
|
|
if (ans1 <= ans2) {
|
|
high = mid2;
|
|
ans = ans1;
|
|
continue;
|
|
}
|
|
|
|
low = mid1;
|
|
ans = ans2;
|
|
}
|
|
|
|
cout << setprecision(12) << ans << '\n';
|
|
}
|
|
}
|