题意:一个宽度固定的纸带,选一个最小的高使其能装下一个给定的三角形
大致思路:枚举三角形一条边在矩形上下边的情况和边靠边的情况。计算几何没什么特别的难点,关键是要耐心,细心。
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
using namespace std;
double eps = 1e-9;
int sign(double x) {
if (fabs(x) < eps) return 0;
return x > 0 ? 1 : -1;
}
double sqr(double x) {
return x * x;
}
struct point {
double x, y;
void read() {
scanf("%lf%lf", &x, &y);
}
void out() {
printf("x = %f y = %f\n", x, y);
}
point(double x = 0, double y = 0) :x(x), y(y) {}
point operator + (const point &rhs) const {
return point(x + rhs.x, y + rhs.y);
}
point operator - (const point &rhs) const {
return point(x - rhs.x, y - rhs.y);
}
point operator * (const double &k) const {
return point(x * k, y * k);
}
point operator / (const double &k) const {
return point(x / k, y / k);
}
point normal() {
double l = sqrt(sqr(x) + sqr(y));
return point(-y / l, x / l);
}
bool operator < (const point &rhs) const {
if (sign(x - rhs.x) == 0) return y < rhs.y;
return x < rhs.x;
}
}p[3];
struct seg {
double len, ang;
}s[3];
double dis(point a, point b) {
return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
}
double cosine(double a, double b, double c) {
return (a * a + b * b - c * c) / (2 * a * b);
}
const double pi = acos(-1);
double w;
int t;
int main() {
scanf("%d", &t);
while (t--) {
for (int i = 0; i < 3; i++) p[i].read();
sort(p, p + 3);
scanf("%lf", &w);
for (int i = 0; i < 3; i++) s[i].len = dis(p[i], p[(i + 1) % 3]);
for (int i = 0; i < 3; i++) s[i].ang = acos(cosine(s[(i + 1) % 3].len, s[(i - 1) < 0 ? 2 : i - 1].len, s[i].len));
double hf = (s[0].len + s[1].len + s[2].len) / 2;
double area = sqrt(hf * (hf - s[0].len) * (hf - s[1].len) * (hf - s[2].len));
if (s[0].len <= w + eps && s[1].len <= w + eps && s[2].len <= w + eps) {
printf("%.9f\n", 2 * area / max({s[0].len, s[1].len, s[2].len}));
continue;
}
double ans = 1e18;
for (int i = 0; i < 3; i++) {
if (s[i].len < w) continue;
point e = point(sqrt(sqr(s[i].len) - sqr(w)), w);
point f1, f2, f3, f4;
point unit = (e / dis(point(), e)) * cos(s[(i - 1) < 0 ? 2 : i - 1].ang) * s[(i + 1) % 3].len;
point vec = e.normal() * (2 * area / s[i].len);
f1 = unit + vec;
f2 = e - unit + vec;
f3 = unit - vec;
f4 = e - unit - vec;
if (f1.y >= -eps && f1.y <= w + eps) ans = min(ans, max({fabs(f1.x - e.x), fabs(f1.x), e.x}));
if (f2.y >= -eps && f2.y <= w + eps) ans = min(ans, max({fabs(f2.x - e.x), fabs(f2.x), e.x}));
if (f3.y >= -eps && f3.y <= w + eps) ans = min(ans, max({fabs(f3.x - e.x), fabs(f3.x), e.x}));
if (f4.y >= -eps && f4.y <= w + eps) ans = min(ans, max({fabs(f4.x - e.x), fabs(f4.x), e.x}));
}
for (int i = 0; i < 3; i++) {
double h = 2 * area / s[i].len;
double ww;
if (s[(i - 1) < 0 ? 2 : i - 1].ang > pi / 2 + eps) {
ww = s[(i - 1) < 0 ? 2 : i - 1].len * fabs(cos(s[(i + 1) % 3].ang));
}
else if (s[(i + 1) % 3].ang > pi / 2 + eps){
ww = s[(i + 1) % 3].len * fabs(cos(s[(i - 1) < 0 ? 2 : i - 1].ang));
}
else ww = s[i].len;
if (h < w + eps) ans = min(ans, ww);
if (ww < w + eps) ans = min(ans, h);
}
if (ans < 1e17) printf("%.9f\n", ans);
else puts("impossible");
}
}