zoukankan      html  css  js  c++  java
  • 【计算几何】URAL

    Little Peter Ivanov likes to play knights. Or musketeers. Or samurai. It depends on his mood. For parents, it is still always looks like “he again found a stick and peels the trees.” They cannot understand that it is a sword. Or epee. Or katana.
    Today Peter has found a shield. Actually, it is a board from the fence; fortunately, the nails from it have already been pulled. Peter knows that the family coat of arms should be depicted on the knight’s shield. The coat of arms of Ivanovs is a rectangle inscribed in a triangle (only grandfather supports Peter’s game, and he is, after all, a professor of mathematics). Peter has already drawn the triangle, and then noticed that there is a hole from a nail inside the triangle. It is not very good, so Peter wants to draw a rectangle in such a way that the hole will be on its border.
    Because of the rectangle in Peter’s family symbolizes the authority and power then Peter wants to draw a rectangle of maximum area.
    And due to the fact, that Peter is a grandson of grandfather-mathematician, he is also interested in purely theoretical question — how many different rectangles, satisfying the conditions, can be drawn in the triangle.
    Help Peter to find the answers to these questions.

    Input

    The four lines contain the coordinates of four points that are the vertices of the triangle and the hole, respectively. All coordinates are integers and do not exceed 10 4 in absolute value. It is guaranteed that the hole is strictly inside the triangle. Also it is guaranteed that the triangle vertices do not lie on one line.

    Output

    In the first line output the maximum area of a rectangle, which Peter can draw. The answer will be considered correct if a relative or absolute error of maximum area does not exceed 10 −6.
    In the second line output the number of different rectangles that Peter can draw (these rectangles are not required to have the maximum area).

    Example

    inputoutput
    0 0
    10 0
    0 20
    4 6
    
    48.0000000000
    4
    
    -3 0
    2 -1
    5 7
    0 1
    
    9.0697674419
    2
    

    Notes

    The rectangle is called inscribed in a triangle if all its vertices lie on the sides of the triangle.

    把三角形按锐角、直角、钝角分类讨论,看点p是否在三条高上。锐角三角形的答案在3-6之间,直角在3-4之间,钝角在1-2之间。

    需要求点在直线上的射影,然后再相似三角形啦,正切函数啥的啦搞一下面积就出来了。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define EPS 0.00000001
    struct Point
    {
    	double x,y;
    	Point(const double &X,const double &Y)
    	  {
    	  	x=X;
    	  	y=Y;	
    	  }
    	Point(){}
    	double Length()
    	  {
    	  	return sqrt(x*x+y*y);
    	  }
    }p,a[4];
    typedef Point Vector;
    double Dot(const Vector &a,const Vector &b)
    {
    	return a.x*b.x+a.y*b.y;
    }
    Vector operator - (const Vector &a,const Vector &b)
    {
    	return Vector(a.x-b.x,a.y-b.y);
    }
    Vector operator + (const Vector &a,const Vector &b)
    {
    	return Vector(a.x+b.x,a.y+b.y);
    }
    double Cross(const Vector &a,const Vector &b)
    {
    	return a.x*b.y-a.y*b.x;
    }
    double DisToLine(Point P,Point A,Point B)
    {
    	Vector v1=B-A,v2=P-A;
    	return fabs(Cross(v1,v2))/v1.Length();
    }
    double tanget(Point a,Point b,Point c)//a是顶点
    {
    	double COS=Dot(b-a,c-a)/(b-a).Length()/(c-a).Length();
    	double SIN=sqrt((1.0-COS*COS));
    	return SIN/COS;
    }
    Vector operator * (const double &x,const Vector &v)
    {
    	return Vector(x*v.x,x*v.y);
    }
    Point GetLineProjection(Point P,Point A,Point B)
    {
    	Vector v=B-A;
    	return A+(Dot(v,P-A)/Dot(v,v))*v;
    }
    double area;
    int main()
    {
    	//freopen("b.in","r",stdin);
    	for(int i=1;i<=3;++i)
    	  scanf("%lf%lf",&a[i].x,&a[i].y);
    	scanf("%lf%lf",&p.x,&p.y);
    	int flag=0,ans=0;
    	//钝角三角形
    	if(Dot(a[2]-a[1],a[3]-a[1])<-EPS)
    	  {
    	  	double dis=DisToLine(p,a[2],a[3]);
    	  	area=dis*((a[2]-a[3]).Length()-dis/tanget(a[2],a[1],a[3])-dis/tanget(a[3],a[1],a[2]));
    	  	if(fabs(Dot(a[1]-p,a[2]-a[3]))<EPS)
    	  	  ans=1;
    	  	else
    	  	  {
    	  	  	ans=2;
    	  	  	Point p1=GetLineProjection(a[1],a[2],a[3]);
    	  	  	Point p2=GetLineProjection(p,a[2],a[3]);
    	  	  	double h=(a[1]-p1).Length();
    	  	  	double h1;
    	  	  	if(Dot(p-p1,a[2]-p1)>EPS)
    	  	  	  h1=(p2-a[2]).Length()/(p1-a[2]).Length()*h;
    	  	  	else
    	  	  	  h1=(p2-a[3]).Length()/(p1-a[3]).Length()*h;
    	  	  	double l1=(h-h1)/h*(a[2]-a[3]).Length();
    	  	  	area=max(area,h1*l1);
    	  	  }
    	  	printf("%.10lf
    %d
    ",area,ans);
    	  	return 0;
    	  }
    	else if(Dot(a[1]-a[2],a[3]-a[2])<-EPS)
    	  {
    	  	double dis=DisToLine(p,a[1],a[3]);
    	  	area=dis*((a[1]-a[3]).Length()-dis/tanget(a[1],a[2],a[3])-dis/tanget(a[3],a[1],a[2]));
    	  	if(fabs(Dot(a[2]-p,a[1]-a[3]))<EPS)
    	  	  ans=1;
    	  	else
    	  	  {
    	  	  	ans=2;
    	  	  	Point p1=GetLineProjection(a[2],a[1],a[3]);
    	  	  	Point p2=GetLineProjection(p,a[1],a[3]);
    	  	  	double h=(a[2]-p1).Length();
    	  	  	double h1;
    	  	  	if(Dot(p-p1,a[1]-p1)>EPS)
    	  	  	  h1=(p2-a[1]).Length()/(p1-a[1]).Length()*h;
    	  	  	else
    	  	  	  h1=(p2-a[3]).Length()/(p1-a[3]).Length()*h;
    	  	  	double l1=(h-h1)/h*(a[1]-a[3]).Length();
    	  	  	area=max(area,h1*l1);
    	  	  }
    	  	printf("%.10lf
    %d
    ",area,ans);
    	  	return 0;
    	  }
    	else if(Dot(a[1]-a[3],a[2]-a[3])<-EPS)
    	  {
    	  	double dis=DisToLine(p,a[1],a[2]);
    	  	area=dis*((a[1]-a[2]).Length()-dis/tanget(a[1],a[2],a[3])-dis/tanget(a[2],a[1],a[3]));
    	  	if(fabs(Dot(a[3]-p,a[1]-a[2]))<EPS)
    	  	  ans=1;
    	  	else
    	  	  {
    	  	  	ans=2;
    	  	  	Point p1=GetLineProjection(a[3],a[1],a[2]);
    	  	  	Point p2=GetLineProjection(p,a[1],a[2]);
    	  	  	double h=(a[3]-p1).Length();
    	  	  	double h1;
    	  	  	if(Dot(p-p1,a[1]-p1)>EPS)
    	  	  	  h1=(p2-a[1]).Length()/(p1-a[1]).Length()*h;
    	  	  	else
    	  	  	  h1=(p2-a[2]).Length()/(p1-a[2]).Length()*h;
    	  	  	double l1=(h-h1)/h*(a[1]-a[2]).Length();
    	  	  	area=max(area,h1*l1);
    	  	  }
    	  	printf("%.10lf
    %d
    ",area,ans);
    	  	return 0;
    	  }
    	//直角三角形
    	if(fabs(Dot(a[2]-a[1],a[3]-a[1]))<EPS)
    	  {
    	  	double dis=DisToLine(p,a[2],a[3]);
    	  	area=dis*((a[2]-a[3]).Length()-dis/tanget(a[2],a[1],a[3])-dis/tanget(a[3],a[1],a[2]));
    	  	if(fabs(Dot(a[1]-p,a[2]-a[3]))<EPS)
    	  	  ans=3;
    	  	else
    	  	  {
    	  	  	ans=4;
    	  	  	Point p1=GetLineProjection(a[1],a[2],a[3]);
    	  	  	Point p2=GetLineProjection(p,a[2],a[3]);
    	  	  	double h=(a[1]-p1).Length();
    	  	  	double h1;
    	  	  	if(Dot(p-p1,a[2]-p1)>EPS)
    	  	  	  h1=(p2-a[2]).Length()/(p1-a[2]).Length()*h;
    	  	  	else
    	  	  	  h1=(p2-a[3]).Length()/(p1-a[3]).Length()*h;
    	  	  	double l1=(h-h1)/h*(a[2]-a[3]).Length();
    	  	  	area=max(area,h1*l1);
    	  	  	
    	  	  	Point p3=GetLineProjection(p,a[1],a[3]);
    	  	  	double h2=(p3-a[3]).Length()/(a[1]-a[3]).Length()*(a[1]-a[2]).Length();
    	  	  	Point p4=GetLineProjection(p,a[1],a[2]);
    	  	  	double l2=(a[1]-a[3]).Length()-h2/tanget(a[3],a[1],a[2]);
    	  	  	area=max(area,h2*l2);
    	  	  	
    	  	  	double h3=(p4-a[2]).Length()/(a[1]-a[2]).Length()*(a[1]-a[3]).Length();
    	  	  	double l3=(a[1]-a[2]).Length()-h3/tanget(a[2],a[1],a[3]);
    	  	  	area=max(area,h3*l3);
    	  	  }
    	  	printf("%.10lf
    %d
    ",area,ans);
    	  	return 0;
    	  }
    	else if(fabs(Dot(a[1]-a[2],a[3]-a[2]))<EPS)
    	  {
    	  	double dis=DisToLine(p,a[1],a[3]);
    	  	area=dis*((a[1]-a[3]).Length()-dis/tanget(a[1],a[2],a[3])-dis/tanget(a[3],a[1],a[2]));
    	  	if(fabs(Dot(a[2]-p,a[1]-a[3]))<EPS)
    	  	  ans=3;
    	  	else
    	  	  {
    	  	  	ans=4;
    	  	  	Point p1=GetLineProjection(a[2],a[1],a[3]);
    	  	  	Point p2=GetLineProjection(p,a[1],a[3]);
    	  	  	double h=(a[2]-p1).Length();
    	  	  	double h1;
    	  	  	if(Dot(p-p1,a[1]-p1)>EPS)
    	  	  	  h1=(p2-a[1]).Length()/(p1-a[1]).Length()*h;
    	  	  	else
    	  	  	  h1=(p2-a[3]).Length()/(p1-a[3]).Length()*h;
    	  	  	double l1=(h-h1)/h*(a[1]-a[3]).Length();
    	  	  	area=max(area,h1*l1);
    	  	  	
    	  	  	Point p3=GetLineProjection(p,a[2],a[3]);
    	  	  	double h2=(p3-a[3]).Length()/(a[2]-a[3]).Length()*(a[1]-a[2]).Length();
    	  	  	Point p4=GetLineProjection(p,a[1],a[2]);
    	  	  	double l2=(a[2]-a[3]).Length()-h2/tanget(a[3],a[1],a[2]);
    	  	  	area=max(area,h2*l2);
    	  	  	
    	  	  	double h3=(p4-a[1]).Length()/(a[1]-a[2]).Length()*(a[2]-a[3]).Length();
    	  	  	double l3=(a[1]-a[2]).Length()-h3/tanget(a[1],a[2],a[3]);
    	  	  	area=max(area,h3*l3);
    	  	  }
    	  	printf("%.10lf
    %d
    ",area,ans);
    	  	return 0;
    	  }
    	else if(fabs(Dot(a[1]-a[3],a[2]-a[3]))<EPS)
    	  {
    	  	double dis=DisToLine(p,a[1],a[2]);
    	  	area=dis*((a[1]-a[2]).Length()-dis/tanget(a[1],a[2],a[3])-dis/tanget(a[2],a[1],a[3]));
    	  	if(fabs(Dot(a[3]-p,a[1]-a[2]))<EPS)
    	  	  ans=3;
    	  	else
    	  	  {
    	  	  	ans=4;
    	  	  	Point p1=GetLineProjection(a[3],a[1],a[2]);
    	  	  	Point p2=GetLineProjection(p,a[1],a[2]);
    	  	  	double h=(a[3]-p1).Length();
    	  	  	double h1;
    	  	  	if(Dot(p-p1,a[1]-p1)>EPS)
    	  	  	  h1=(p2-a[1]).Length()/(p1-a[1]).Length()*h;
    	  	  	else
    	  	  	  h1=(p2-a[2]).Length()/(p1-a[2]).Length()*h;
    	  	  	double l1=(h-h1)/h*(a[1]-a[2]).Length();
    	  	  	area=max(area,h1*l1);
    	  	  	
    	  	  	Point p3=GetLineProjection(p,a[2],a[3]);
    	  	  	double h2=(p3-a[2]).Length()/(a[2]-a[3]).Length()*(a[1]-a[3]).Length();
    	  	  	Point p4=GetLineProjection(p,a[1],a[3]);
    	  	  	double l2=(a[2]-a[3]).Length()-h2/tanget(a[2],a[1],a[3]);
    	  	  	area=max(area,h2*l2);
    	  	  	
    	  	  	double h3=(p4-a[1]).Length()/(a[1]-a[3]).Length()*(a[2]-a[3]).Length();
    	  	  	double l3=(a[1]-a[3]).Length()-h3/tanget(a[1],a[2],a[3]);
    	  	  	area=max(area,h3*l3);
    	  	  }
    	  	printf("%.10lf
    %d
    ",area,ans);
    	  	return 0;
    	  }
    	//锐角三角形
    	for(int i=1;i<=3;++i)//枚举上顶点
    	  {
    	  	int j,k;
    	  	if(i==1) j=2,k=3;
    	  	else if(i==2) j=3,k=1;
    	  	else j=1,k=2;
    	  	double dis=DisToLine(p,a[j],a[k]);
    	  	area=max(area,dis*((a[j]-a[k]).Length()-dis/tanget(a[j],a[i],a[k])-dis/tanget(a[k],a[i],a[j])));
    	  	if(fabs(Dot(a[i]-p,a[k]-a[j]))<EPS)
    	  	  ++ans;
    	  	else
    	  	  {
    	  	  	ans+=2;
    	  		Point p1=GetLineProjection(a[i],a[j],a[k]);
    	  	  	Point p2=GetLineProjection(p,a[j],a[k]);
    	  	  	double h=(a[i]-p1).Length();
    	  	  	double h1;
    	  	  	if(Dot(p-p1,a[j]-p1)>EPS)
    	  	  	  h1=(p2-a[j]).Length()/(p1-a[j]).Length()*h;
    	  	  	else
    	  	  	  h1=(p2-a[k]).Length()/(p1-a[k]).Length()*h;
    	  	  	double l1=(h-h1)/h*(a[j]-a[k]).Length();
    	  	  	area=max(area,h1*l1);
    	  	  }
    	  }
    	printf("%.10lf
    %d
    ",area,ans);
    	return 0;
    }
  • 相关阅读:
    学了axure的感受
    axure的功能
    PS的应用
    day15-1 模块
    day14-2 模块详解
    day14-1 模块定义,导入
    day13-1 Json & pickle 数据序列化
    day12-3 内置方法
    day12-2 内置方法
    day12-1 迭代器和生成器
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6303275.html
Copyright © 2011-2022 走看看