hdu 6398 Pizza Hub

题解:枚举每条边,每条边考虑三种情况,当前边(重合于x轴,重合于y轴,倾斜x轴某一角度A)

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int mod = 998244353;
const int MX = 1e5+7;
const double eps = 1e-12;
const double PI = acos(-1.0);

struct Point {
    double x, y;
    Point() {}
    Point(double x,double y):x(x),y(y) {}
};
typedef Point Vector;
int dcmp(double x) { //返回x的正负
    if(fabs(x)<eps)return 0;
    return x<0?-1:1;
}
Vector operator-(Vector A,Vector B) {return Vector(A.x - B.x, A.y - B.y);}
Vector operator+(Vector A,Vector B) {return Vector(A.x + B.x, A.y + B.y);}
Vector operator*(Vector A,double p) {return Vector(A.x*p, A.y*p);}
Vector operator/(Vector A,double p) {return Vector(A.x/p, A.y/p);}
bool operator<(const Point&a,const Point&b) {return a.x<b.x||(a.x==b.x&&a.y<b.y);}
bool operator==(const Point&a,const Point&b) {return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;}
double Dot(Vector A,Vector B) { //点积
    return A.x*B.x+A.y*B.y;//如果改成整形记得加LL
}
double Cross(Vector A,Vector B) { //叉积
    return A.x*B.y-A.y*B.x;//如果改成整形记得加LL
}
//向量长度
double Length(Vector A) {
    return sqrt(Dot(A,A));
}
//2个向量之间的夹角
double Angle(Vector A,Vector B) {
    return acos(Dot(A,B)/Length(A)/Length(B));
}
//向量的极角
double angle(Vector v) {
    return atan2(v.y,v.x);
}
//计算ABC的有向面积
double Area(Point A,Point B,Point C) {
    return Cross(B-A,C-A)/2;
}
//将A向量逆时针旋转rad
Vector Rotate( Vector A,double rad) {
    return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
//返回A的逆时针旋转90度的单位法向量
Vector Normal(Vector A) {
    double L=Length(A);
    return Vector(-A.y/L,A.x/L);
}



int main() {
#ifdef LOCAL
    freopen ("input.txt", "r", stdin);
#endif
    int T;
    Point p[5];

    double len[5];
    double ang[5];
    double w;
    for(scanf("%d",&T); T; T--){
        for(int i = 0; i < 3; i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        scanf("%lf",&w);

        len[0] = Length(p[0]-p[1]); len[1] = Length(p[1]-p[2]); len[2] = Length(p[2]-p[0]);
        ang[0] = Angle(p[0]-p[2],p[1]-p[2]);
        ang[1] = Angle(p[1]-p[0],p[2]-p[0]);
        ang[2] = Angle(p[2]-p[1],p[0]-p[1]);

        int n = 3;
        double ans = 100000;
        for(int i = 0; i < 3; i++){
            double minang = ang[(i-1+3)%3], maxang = ang[(i+1)%3];
            if(minang > maxang) swap(minang,maxang);
            double minlen = len[(i-1+3)%3], maxlen = len[(i+1)%3];
            if(minlen > maxlen) swap(minlen,maxlen);

            Point dot = Point(0,0);
            Vector v = Point(1,0);
            //平躺
            if(dcmp(len[i] - w) <= 0){
                dot = Point(Rotate(v*maxlen, minang));
                if(dcmp(dot.x) >= 0 && dcmp(dot.x - w) <= 0 && dot.y > 0) ans = min(ans,dot.y);

                dot = Point(Rotate(v*minlen, maxang));
                if(dcmp(dot.x) >= 0 && dcmp(dot.x - w) <= 0 && dot.y > 0) ans = min(ans,dot.y);
            }

            //竖直
            double minang2 = PI/2 - minang, maxang2 = PI/2 - maxang;
            dot = Point(Rotate(v*maxlen, minang2));
            if(dcmp(dot.x) >= 0 && dcmp(dot.x - w) <= 0 && dot.y > 0) ans = min(ans,max(dot.y,len[i]) );
            dot = Point(Rotate(v*minlen, maxang2));
            if(dcmp(dot.x) >= 0 && dcmp(dot.x - w) <= 0 && dot.y > 0) ans = min(ans,max(dot.y,len[i]) );

            //斜着
            if(len[i] > w){
                double A = acos(w/len[i]);
                Vector d = Point(Rotate(v*len[i], A));

                dot = Point(Rotate(v*maxlen, A-minang));
                if(dcmp(dot.x) >= 0 && dcmp(dot.x - w) <= 0 && dot.y > 0) ans = min(ans,max(dot.y,d.y));
                dot = Point(Rotate(v*maxlen, A+minang));
                if(dcmp(dot.x) >= 0 && dcmp(dot.x - w) <= 0 && dot.y > 0) ans = min(ans,max(dot.y,d.y));

                dot = Point(Rotate(v*minlen, A-maxang));
                if(dcmp(dot.x) >= 0 && dcmp(dot.x - w) <= 0 && dot.y > 0) ans = min(ans,max(dot.y,d.y));
                dot = Point(Rotate(v*minlen, A+maxang));
                if(dcmp(dot.x) >= 0 && dcmp(dot.x - w) <= 0 && dot.y > 0) ans = min(ans,max(dot.y,d.y));
            }
        }
        if(dcmp(ans-100000) == 0) puts("impossible");
        else printf("%.8f\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值