题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6398
这题做了一天真是恶心!!!计算几何的题目都是这样。。。
计算几何需要注意的最大的问题就是角度或者sin、cos的值的大小判断是一个模糊的界限,不管哪一个比较大,只要差值不超过
规定的eps(一般是1e-6)就可以视为是相等的。不能单纯地用大于号或者小于号判断。
如a>b,但是fabs(a-b)<eps,则此时a=b。
这道题分为两种情况
①三角形的一条边与矩形底边重合
②三角形一个顶点卡在矩形角上,另一个搭在对面的一条边上。
一共是3+6*2=15种情况,计算最小值即可,只是debug太恶心了
注释就不删了,留着以后自己可能会看。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
#define sqr(a) a*a
using namespace std;
const int maxn=303;
const double pi=atan(1.0)*4;
const double len=1.0001*1.0001;
//基础点和向量运算
struct Point{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
};
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);}
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);
}
const double eps=1e-6;
int dcmp(double x)//判断正负,或者等于0
{
if(fabs(x)<eps)return 0;else return x<0?-1:1;
}
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;}//点积
double Length(Vector A){return sqrt(Dot(A,A));}//OA长
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Length(A)/Length(B));}//OA和OB的夹角
double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}//叉积
double Area2(Point A,Point B,Point C){return Cross(B-A,C-A);}//三角形面积
Vector Rotate(Vector A,double rad)//rad为弧度,旋转rad度
{
return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
Vector Normal(Vector A)//A的单位法向量,A不能为零向量
{
double L=Length(A);
return Vector(-A.y/L,A.x/L);
}
int main()
{
// freopen("b.in","r",stdin);
//
// freopen("2.txt","w",stdout);
int t;
scanf("%d",&t);
while(t--)
{
double x1,y1,x2,y2,x3,y3,w;
scanf("%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&w);
Point a=Point(x1,y1);
Point b=Point(x2,y2);
Point c=Point(x3,y3);
double s=Area2(a,b,c);
double minn=inf;
///①:其中一条边与矩形底边重合
if(Length(a-b)<=w)
{
double tem=fabs(Length(c-a)*cos(Angle(b-a,c-a)));
double tem1=fabs(Length(c-b)*cos(Angle(a-b,c-b)));
// printf("a,b tem1=%lf tem2=%lf\n",tem,tem1);
if(tem1<=w&&tem<=w)
minn=min(minn,Length(c-a)*sin(Angle(b-a,c-a)));
// printf("%lf %lf\n",cos(Angle(b-a,c-a)),(sqr(Length(b-a))+sqr(Length(c-a))-sqr(Length(b-c)))/(2*Length(b-a)*Length(c-a)));
// printf("%lf\n",Area2(a,b,c)*2/Length(b-a));
}
if(Length(c-b)<=w)
{
double tem=fabs(Length(a-c)*cos(Angle(b-c,a-c)));
double tem1=fabs(Length(a-b)*cos(Angle(c-b,a-b)));
// printf("b,c tem1=%lf tem2=%lf\n",tem,tem1);
if(tem1<=w&&tem<=w)
minn=min(minn,Length(a-c)*sin(Angle(b-c,a-c)));
}
if(Length(a-c)<=w)
{
double tem=fabs(Length(b-a)*cos(Angle(b-a,c-a)));
double tem1=fabs(Length(b-c)*cos(Angle(b-c,a-c)));
// printf("a,c tem1=%lf tem2=%lf\n",tem,tem1);
if(tem1<=w&&tem<=w)
minn=min(minn,Length(b-a)*sin(Angle(b-a,c-a)));
}
// printf("minn=%lf\n",minn);
///②:两点卡在矩形边上
double len,a1,b1,c1;
///顶点为a,b在边上
len=Length(a-b);
if(len>w)
{
a1=acos(w/len);
b1=Angle(c-a,b-a);
if(b1<a1)
{
c1=a1-b1;
double tem=w/cos(c1);
if(tem>Length(c-a))
minn=min(minn,tan(a1)*w);
}
//printf("a,b minn=%lf\n",minn);
if(a1+b1<pi/2||fabs(pi/2-a1-b1)<eps)
{
double tem=w/cos(a1+b1);
if(tem>Length(c-a)||fabs(pi/2-a1-b1)<eps)
{
minn=min(minn,max(Length(c-a)*sin(a1+b1),tan(a1)*w));
// minn=min(minn,tan(a1)*w);
}
}
}
//printf("a,b minn=%lf\n",minn);
///顶点为a,c在边上
len=Length(a-c);
if(len>w)
{
a1=acos(w/len);
b1=Angle(c-a,b-a);
// printf("a1=%lf b1=%lf\n",a1,cos(b1));
if(b1<a1)
{
c1=a1-b1;
double tem=w/cos(c1);
if(tem>Length(b-a))
minn=min(minn,tan(a1)*w);
}
if(a1+b1<pi/2||fabs(pi/2-a1-b1)<eps)
{
double tem=w/cos(a1+b1);
if(tem>Length(b-a)||fabs(pi/2-a1-b1)<eps)
{
minn=min(minn,max(Length(b-a)*sin(a1+b1),tan(a1)*w));
}
}
}
//printf("a,c minn=%lf\n",minn);
///顶点为b,a在边上
len=Length(b-a);
if(len>w)
{
a1=acos(w/len);
b1=Angle(a-b,c-b);
// printf("a1=%lf b1=%lf %.20lf %.20lf\n",a1,b1,a1+b1,fabs(pi/2-a1-b1));
if(b1<a1)
{
c1=a1-b1;
double tem=w/cos(c1);
if(tem>Length(c-b))
minn=min(minn,tan(a1)*w);
}
if(a1+b1<pi/2||fabs(pi/2-a1-b1)<eps)
{
double tem=w/cos(a1+b1);
// printf("ok\n");
// if(fabs(pi/2-a1-b1)<eps)
// minn=min(minn,max(Length(c-b)*sin(a1+b1),tan(a1)*w));
if(tem>Length(c-b)||fabs(pi/2-a1-b1)<eps)
{
// printf("%lf %lf\n",Length(c-b)*sin(a1+b1),tan(a1)*w);
minn=min(minn,max(Length(c-b)*sin(a1+b1),tan(a1)*w));
}
}
}
//printf("b,a minn=%lf\n",minn);
///顶点为b,c在边上
len=Length(b-c);
if(len>w)
{
a1=acos(w/len);
b1=Angle(a-b,c-b);
// printf("a1=%lf b1=%lf\n",a1,b1);
if(b1<a1)
{
c1=a1-b1;
double tem=w/cos(c1);
if(tem>Length(a-b))
minn=min(minn,tan(a1)*w);
}
if(a1+b1<pi/2||fabs(pi/2-a1-b1)<eps)
{
double tem=w/cos(a1+b1);
if(tem>Length(a-b)||fabs(pi/2-a1-b1)<eps)
{
minn=min(minn,max(Length(a-b)*sin(a1+b1),tan(a1)*w));
}
}
}
//printf("b,c minn=%lf\n",minn);
///顶点为c,a在边上
len=Length(a-c);
if(len>w)
{
a1=acos(w/len);
b1=Angle(a-c,b-c);
// printf("a1=%lf b1=%lf\n",a1,b1);
if(b1<a1)
{
c1=a1-b1;
// printf("c1=%lf\n",c1);
double tem=w/cos(c1);
// printf("tem=%lf\n len(b-c)=%lf\n",tem,Length(b-c));
if(tem>Length(b-c))
minn=min(minn,tan(a1)*w);//printf("1 min:%lf\n",tan(a1)*w);
}
if(a1+b1<pi/2||fabs(pi/2-a1-b1)<eps)
{
double tem=w/cos(a1+b1);
if(tem>Length(b-c)||fabs(pi/2-a1-b1)<eps)
{
minn=min(minn,max(Length(b-c)*sin(a1+b1),tan(a1)*w));//printf("2 min:%lf\n",Length(b-c)*sin(a1+b1));
}
}
}
//printf("c,a minn=%lf\n",minn);
///顶点为c,b在边上
len=Length(b-c);
if(len>w)
{
a1=acos(w/len);
b1=Angle(a-c,b-c);
// printf("a1=%lf b1=%lf\n",a1,b1);
if(b1<a1)
{
c1=a1-b1;
double tem=w/cos(c1);
if(tem>Length(a-c))
minn=min(minn,tan(a1)*w);//printf("1 min:%lf\n",tan(a1)*w);
}
if(a1+b1<pi/2||fabs(pi/2-a1-b1)<eps)
{
double tem=w/cos(a1+b1);
if(tem>Length(a-c)||fabs(pi/2-a1-b1)<eps)
{
minn=min(minn,max(Length(a-c)*sin(a1+b1),tan(a1)*w));//printf("2 min:%lf\n",Length(a-c)*sin(a1+b1));;
}
}
}
//printf("c,b minn=%lf\n",minn);
if(minn!=inf)
printf("%.9lf\n",minn);
else
printf("impossible\n");
}
return 0;
}