题意:
给一个三角形,放在一个给定宽度的无线长的矩形中,要求占得长度最小。
题解:
分两种情况,一是三角形的边与矩形的边重合,二是三角形的两个点卡在矩形的两条边上。
对于第一种情况,枚举底边,算出第三点在底边的投影,就知道要占据的最小宽度,若小于等于矩形宽度,再算出占据的高度。
对于第二种情况,枚举卡在矩形的两条边上的两个点,算出该边与矩形宽度的夹角,第三点若在矩形内,再算出占据的高度。
代码:
#include<bits/stdc++.h>
#define N 100010
#define INF 0x3f3f3f3f
#define LL long long
#define pb push_back
#define cl clear
#define si size
#define lb lowwer_bound
#define eps 1e-8
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define pi 3.141592653589793
using namespace std;
int dcmp(double x){if (fabs(x)<eps)return 0;else return x<0?-1:1;}
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){ }
};
Point a[3]; double d,ans; int fg;
typedef Point Vector;
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);}
double Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;} //点积
double Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;} //叉积
double Length(Vector a){return sqrt(Dot(a,a));}
Vector operator * (Vector a,double b){return Vector(a.x*b,a.y*b);}
double Angle(Vector a,Vector b){return acos(Dot(a,b)/Length(a)/Length(b));}// 范围[0,180]
//点到直线ab的投影
Point GetLineProjection(Point p,Point a,Point b)
{
Vector v=b-a;
return a+v*(Dot(v,p-a)/Dot(v,v));
}
double Max(Point i,Point j,Point k)
{
return max(Length(i-j),max(Length(i-k),Length(j-k)));
}
void check(int i,int j,int k)
{
Point v=GetLineProjection(a[k],a[i],a[j]);
if (dcmp(Max(v,a[i],a[j])-d)<=0) fg=1,ans=min(ans,Length(v-a[k]));
}
//极角,范围[0,360)
double JJ(Vector a)
{
double x=atan2(a.y,a.x);
if (a.y<0)x+=pi*2;
return x;
}
Vector Rotate(Vector a,double rad)// 向量 a 逆时针旋转 rad
{return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));}
void checkk(int i,int j,Point k)
{
double l=Length(a[i]-a[j]);
double ang=acos(min(d/l,1.0));
if (Cross(k-a[i],a[j]-a[i])>0) swap(i,j);
if (dcmp(Angle(k-a[i],a[j]-a[i])+ang-pi*0.5)<=0 &&
dcmp(Angle(k-a[j],a[i]-a[j])-ang-pi*0.5)<=0)
{
fg=1;
Point v1=a[j]-a[i],v2=k-a[i];
double aa=JJ(v1)-pi*2;
v2=Rotate(v2,ang-aa);
v1=Rotate(v1,ang-aa);
double t1=max(0.0,max(v1.y,v2.y)),
t2=min(0.0,min(v1.y,v2.y));
ans=min(ans,t1-t2);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
for (int i=0;i<3;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
scanf("%lf",&d);
fg=0; ans=1e9;
for (int i=0;i<3;i++) check(i,(i+1)%3,(i+2)%3);
for (int i=0;i<3;i++)
{
checkk(i,(i+1)%3,a[(i+2)%3]);
Point v=GetLineProjection(a[(i+2)%3],a[i],a[(i+1)%3]);
checkk(i,(i+1)%3,v*2-a[(i+2)%3]);
}
if (fg) printf("%.8f\n", ans );else puts("impossible");
}
}