HDU-6398:Pizza Hub(计算几何)

Pizza Hub
Time Limit: 3000/3000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
Special Judge

Problem Description
Coffee Chicken has started a new restaurant named Pizza Hu…b! It provides various styles of pizzas, hamburgers, sandwiches, coffee, chickens and many other awesome Western cuisines. Welcome to Pizza Hub after this Multi-University Training Contest!

Since the pizzas are so exquisite, it is never a bad thing to design nice paper pads for them. The pizzas provided in Pizza Hub are sliced into triangles. The rectangular-shaped paper pads are cut from a paper strip of fixed width which is long enough. The pizza should be placed entirely on the pad; however, their borders are allowed to touch. Also, you are allowed to rotate the pizza.

As the customized paper strip is rather expensive, minimizing the size of the pizza pad can save a lot of money. Can you determine the minimum possible height of the pizza pad, given the width of the paper strip? The following picture illustrates the first sample test case.
这里写图片描述

Input
The first line of the input is a single integer T(1T50000) T ( 1 ≤ T ≤ 50000 ) , the number of test cases.

Each test case is a single line of seven integers x1,y1,x2,y2,x3,y3(0x1,y1,x2,y2,x3,y310000) x 1 , y 1 , x 2 , y 2 , x 3 , y 3 ( 0 ≤ x 1 , y 1 , x 2 , y 2 , x 3 , y 3 ≤ 10000 ) and w(1w10000) w ( 1 ≤ w ≤ 10000 ) , where (x1,y1),(x2,y2) ( x 1 , y 1 ) , ( x 2 , y 2 ) and (x3,y3) ( x 3 , y 3 ) are Cartesian coordinates of the vertices of the pizza, and w is the width of the strip. It is guaranteed that the three vertices are not collinear.

Output
For each test case, display the minimum height of the pizza pad with an absolute or relative error of no more than 106 10 − 6 . If it is impossible to make a pizza pad, display impossible instead.

Sample Input
2
0 0 3 0 0 4 10
0 0 3 0 0 4 1

Sample Output
2.400000000
impossible

题解:注意到总存在一个最优解,使得矩形的一个顶点和三角形的一个顶点重合。然后只要枚举所有可能的放置方法即可。
实现的时候需要特别注意边界条件的判断。
这里写图片描述
这里写图片描述

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=998244353;
const int INF=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
struct Point{ll x,y;}p[10];
Point operator-(Point A,Point B){return (Point){A.x-B.x,A.y-B.y};}
double dis(Point A,Point B){return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
ll operator*(Point A,Point B){return A.x*B.x+A.y*B.y;}
ll operator^(Point A,Point B){return A.x*B.y-A.y*B.x;}
ll cross(Point A,Point B){return A.x*B.y-A.y*B.x;}
ll dis2(Point A,Point B){return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}     //A B两点的距离的平方
double ans;
void cal(Point a,Point b,ll w)
{
    ll area=abs(a^b);
    if(a*b<0)return;//ab间夹角为钝角,即一定有条边超出矩形范围
    if(a*a<=w*w)    //将线段a平放在底面
    {
        if((a^b)<0)return;                //点b在向量a的下方
        if((a*b)*(a*b)>w*w*(a*a))return;  //向量b在底面上的投影长度大于w
        ans=min(ans,area/sqrt(a*a));
    }
    else            //将线段a倾斜放置
    {
        double h=sqrt(a*a-w*w);
        double A=atan(h/w);     //向量a与底面的夹角
        double B=PI/2-A;
        if((a^b)>=0)            //b点在向量a的上方
        {
            double AB=acos(a*b/(sqrt(a*a)*sqrt(b*b)));
            if(AB-B>1e-9)return;//向量b从侧面超出矩形范围
            double L=sqrt(b*b)*cos(A+AB);
            if(L-w>0)return;    //向量b在底面上的投影长度大于w
            ans=min(ans,max(h,sqrt(b*b)*sin(AB+A)));
        }
        else                   //b点在向量a的下方
        {
            double AB=acos(a*b/(sqrt(a*a)*sqrt(b*b)));
            if(AB-A>1e-9)return;//向量b从下方超出矩形范围
            double L=sqrt(b*b)*cos(A-AB);
            if(L-w>0)return;    //向量b在底面上的投影长度大于w
            ans=min(ans,h);
        }
    }
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        ll w;
        for(int i=1;i<=3;i++)scanf("%lld%lld",&p[i].x,&p[i].y);
        scanf("%lld",&w);
        ans=1e9+7;
        cal(p[3]-p[1],p[2]-p[1],w);
        cal(p[2]-p[1],p[3]-p[1],w);
        cal(p[3]-p[2],p[1]-p[2],w);
        cal(p[1]-p[2],p[3]-p[2],w);
        cal(p[1]-p[3],p[2]-p[3],w);
        cal(p[2]-p[3],p[1]-p[3],w);
        for(int i=1;i<=3;i++)p[i].y=-p[i].y;
        cal(p[3]-p[1],p[2]-p[1],w);
        cal(p[2]-p[1],p[3]-p[1],w);
        cal(p[3]-p[2],p[1]-p[2],w);
        cal(p[1]-p[2],p[3]-p[2],w);
        cal(p[1]-p[3],p[2]-p[3],w);
        cal(p[2]-p[3],p[1]-p[3],w);
        if(ans>=1e9)puts("impossible");
        else printf("%.9f\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值