hdu6398

非常细的分类讨论

题意是,给定三角形,给定矩形的宽,问这个三角形是否能放到这样的矩形里,并求最小的高。
这题当时没想出来有一种极其细长的钝角三角形。。那样的三角形会多带来许多bug。。把那些情况去掉即可。。
剩下的就是考虑w是怎么放的:

  1. 与一条边重合
  2. 和一条边+高刚好卡成一个三角形(这样肯定是最小的)。

    但注意在这种情况中,还有可能中间的铅垂高不一定是最大的(卡对角线),又被坑了一下。。

#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;
        }
    }
}