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(1≤T≤50000) 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(0≤x1,y1,x2,y2,x3,y3≤10000) 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(1≤w≤10000) 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 10−6 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
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;
}