Description
给出二维平面三角形的三个顶点坐标,现在要将这个三角形经过任意旋转使得其可以放在一个宽为ww的矩形中,问该矩形的高度最小值
Input
第一行一整数表示用例组数,每组用例输入七个整数x1,y1,x2,y2,x3,y3,wx1,y1,x2,y2,x3,y3,w分别表示三点坐标和矩形的宽
(1≤T≤50000,0≤x1,y1,x2,y2,x3,y3≤10000,1≤w≤10000)(1≤T≤50000,0≤x1,y1,x2,y2,x3,y3≤10000,1≤w≤10000)
Output
如果无解则输出impossibleimpossible,否则输出矩形高的最小值
Sample Input
2
0 0 3 0 0 4 10
0 0 3 0 0 4 1
Sample Output
2.400000000
impossible
Solution
简单分析可知三角形必然可以有一个顶点与该长方形底边一角重合,假设AA点与底角重合,那么有三种情况:
1.三角形一边在底部
2.点在边上
3.CC点在边上
三种情况均有另一个点不在矩形区域的不合法状态,枚举三个点的顺序以及这三种情况更新答案即可
Code
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define eps 1e-9
#define INF 1e9
double x[3],y[3],w,ans;
int T;
int sgn(double x)
{
if(fabs(x)<eps)return 0;
if(x>=eps)return 1;
return -1;
}
double get_a(double a,double b,double c)
{
return acos((a*a+b*b-c*c)/(2.0*a*b));
}
double get_s(double a,double b,double c)
{
double s=0.5*(a+b+c);
return sqrt(s*(s-a)*(s-b)*(s-c));
}
double get_d(int i,int j)
{
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
void Solve(double ab,double ac,double bc)
{
double A=get_a(ab,ac,bc);
if(sgn(ab*sin(A)-w)>0||sgn(A-0.5*PI)>0)return ;
if(sgn(w-max(ab,ac*cos(A)))>=0)
{
ans=min(ans,ac*sin(A));
return ;
}
if(sgn(ab-w)>=0)
{
double a=acos(w/ab);
if(sgn(w-ac*cos(a+A))>=0&&sgn(0.5*PI-a-A)>=0)
ans=min(ans,max(ac*sin(a+A),sqrt(ab*ab-w*w)));
}
if(sgn(ac*cos(A)-w)>=0)
{
double a=acos(w/ac);
if(sgn(a-A)>=0&&sgn(w-ab*cos(a-A))>=0)
ans=min(ans,sqrt(ac*ac-w*w));
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
for(int i=0;i<3;i++)scanf("%lf%lf",&x[i],&y[i]);
scanf("%lf",&w);
double d[3];
d[0]=get_d(0,1),d[1]=get_d(0,2),d[2]=get_d(1,2);
ans=INF;
int a[3]={0,1,2};
do
{
Solve(d[a[0]],d[a[1]],d[a[2]]);
}while(next_permutation(a,a+3));
if(sgn(ans-INF)==0)printf("impossible\n");
else printf("%.9f\n",ans);
}
return 0;
}