hdu6398
非常细的分类讨论
题意是,给定三角形,给定矩形的宽,问这个三角形是否能放到这样的矩形里,并求最小的高。
这题当时没想出来有一种极其细长的钝角三角形。。那样的三角形会多带来许多bug。。把那些情况去掉即可。。
剩下的就是考虑w是怎么放的:
- 与一条边重合
- 和一条边+高刚好卡成一个三角形(这样肯定是最小的)。
但注意在这种情况中,还有可能中间的铅垂高不一定是最大的(卡对角线),又被坑了一下。。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
#define double long double
const double EPS = 1e-6;
struct Point
{
Point() {}
Point(double _x, double _y): x(_x), y(_y) {}
double getDis(Point rhs)
{
double xx = rhs.x - x, yy = rhs.y - y;
return sqrt(xx * xx + yy * yy);
}
void input(){cin >> x >> y;}
double x, y;
};
double operator ^(Point lhs, Point rhs){return lhs.x * rhs.y - lhs.y * rhs.x;}
Point operator +(Point lhs, Point rhs){return Point(lhs.x + rhs.x, lhs.y + rhs.y);}
Point operator -(Point lhs, Point rhs){return Point(lhs.x - rhs.x, lhs.y - rhs.y);}
Point operator /(Point lhs, double rhs){return Point(lhs.x / rhs, lhs.y / rhs);}
Point operator *(Point lhs, double rhs){return Point(lhs.x * rhs, lhs.y * rhs);}
double operator *(Point lhs, Point rhs){return lhs.x * rhs.x + lhs.y * rhs.y;}
Point a, b, c;
double w;
double d[3], p, area;
double check(double base, double left, double right)
{
// cout << "check " << base << ' ' << left << ' ' << right << endl;
double cosbl = (left * left + base * base - right * right) / (2.0 * base * left);
if(cosbl <= -EPS) return -2;
double sinbl = sqrt(1.0 - cosbl * cosbl);
double cosbw = w / base;
double sinbw = sqrt(1.0 - cosbw * cosbw);
double coswl = cosbw * cosbl - sinbl * sinbw;
if(coswl <= -EPS) return -2;
if(left * coswl >= w - EPS) return -2;
double sinwl = sqrt(1.0 - coswl * coswl);
// cout << "coswl " << coswl << endl;
// cout << "l1 " << left * sinwl << "\tl2 " << base * sinbw << endl;
// cout << "ans " << max(left * sinwl, base * sinbw) << endl << endl;
return max(left * sinwl, base * sinbw);
}
bool inRange(double a, double b, double c)
{
double cos1 = (a * a + b * b - c * c) / (2.0 * a * b);
double cos2 = (a * a + c * c - b * b) / (2.0 * a * c);
if(cos1 >= -EPS && cos2 >= -EPS)
{
return true;
}
double cosd;
if(cos1 >= EPS) cosd = cos1;
else cosd = cos2;
return max(b, c) * cosd <= w + EPS;
}
double ok1()
{
if(d[0] <= w + EPS)
{
if(inRange(d[0], d[1], d[2]))
{
double h = area * 2.0 / d[0];
return h;
}
}
else
{
double ans1 = check(d[0], d[1], d[2]);
double ans2 = check(d[0], d[2], d[1]);
if(ans1 >= 0 && ans2 >= 0)
{
return min(ans1, ans2);
}
if(ans1 >= 0)
{
return ans1;
}
if(ans2 >= 0)
{
return ans2;
}
}
return -2;
}
double ok2()
{
if(d[1] <= w + EPS)
{
if( inRange(d[1], d[0], d[2]))
{
double h = area * 2.0 / d[1];
return h;
}
}
else
{
double ans1 = check(d[1], d[0], d[2]);
double ans2 = check(d[1], d[2], d[0]);
if(ans1 >= 0 && ans2 >= 0)
{
return min(ans1, ans2);
}
if(ans1 >= 0)
{
return ans1;
}
if(ans2 >= 0)
{
return ans2;
}
}
return -2;
}
double ok3()
{
if(d[2] <= w + EPS )
{
if(inRange(d[2], d[0], d[1]))
{
double h = area * 2.0 / d[2];
return h;
}
}
else
{
double ans1 = check(d[2], d[1], d[0]);
double ans2 = check(d[2], d[0], d[1]);
if(ans1 >= 0 && ans2 >= 0)
{
return min(ans1, ans2);
}
if(ans1 >= 0)
{
return ans1;
}
if(ans2 >= 0)
{
return ans2;
}
}
return -2;
}
int main()
{
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout.precision(9);
cout << fixed;
int T;
cin >> T;
while(T--)
{
double ans;
double temp;
bool possible = false;
a.input();
b.input();
c.input();
cin >> w;
d[0] = a.getDis(b);
d[1] = b.getDis(c);
d[2] = c.getDis(a);
p = d[0] + d[1] + d[2];
p /= 2.0;
area = sqrt(p * (p - d[0]) * (p - d[1]) * (p - d[2]));
temp = ok1();
if(temp >= 0)
{
if(!possible)
{
possible = true;
ans = temp;
}
else
{
ans = min(ans, temp);
}
}
temp = ok2();
if(temp >= 0)
{
if(!possible)
{
possible = true;
ans = temp;
}
else
{
ans = min(ans, temp);
}
}
temp = ok3();
if(temp >= 0)
{
if(!possible)
{
possible = true;
ans = temp;
}
else
{
ans = min(ans, temp);
}
}
if(!possible) cout << "impossible" << endl;
else
{
cout << ans << endl;
}
}
}