记录编号 375906 评测结果 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
题目名称 大灾变 最终得分 100
用户昵称 GravatarNew World 是否通过 通过
代码语言 C++ 运行时间 5.008 s
提交时间 2017-02-26 10:17:22 内存使用 72.41 MiB
显示代码纯文本
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
#define Inf 2e100
#define eps 1e-12
const int maxn=1050000;
struct Point{
	double x,y;
	Point(double xx=0,double yy=0){x=xx;y=yy;}
	void input(){scanf("%lf%lf",&x,&y);}
	void output(){printf("<<%.3lf %.3lf>>",x,y);}
};
typedef Point Vector;

int dcmp(double x)
{return fabs(x)<eps ? 0 : x>0 ? 1 :-1;}

bool operator == (Vector A,double x)
{return dcmp(A.x-x)==0 && dcmp(A.y-x)==0;}

bool operator < (Point A,Point B)
{return A.x!=B.x ? A.x<B.x : A.y<B.y;}

Vector operator - (Point A,Point B)
{return Vector(A.x-B.x,A.y-B.y);}

Point operator + (Point A,Vector B)
{return Point(A.x+B.x,A.y+B.y);}

Vector operator * (Vector A,double x)
{return Vector(A.x*x,A.y*x);}

double Cross(Vector A,Vector B)
{return A.x*B.y-A.y*B.x;}

double Dot(Vector A,Vector B)
{return A.x*B.x+A.y*B.y;}

double Length(Vector A)
{return sqrt(Dot(A,A));}

struct Line{
	Point P;Vector v;
	double ang;
	Line(){};
	Line(Point A,Vector B){
		P=A;v=B;
		ang=atan2(v.y,v.x);
	}
	bool operator < (const Line & A)const{
		return ang<A.ang;
	}
};

bool OnLeft(Line L,Point P)
{return dcmp(Cross(L.v,P-L.P))>=0;}

Point LineInterSection(Line A,Line B){
	if(B.v==0 && A.v==0)return Point(Inf,Inf);
	if(B.v==0){
		if(dcmp(Cross(A.v,B.P-A.P))==0)return B.P;
	}
	if(A.v==0){
		if(dcmp(Cross(B.v,A.P-B.P))==0)return A.P;
	}
	Vector u=A.P-B.P;
	double t=Cross(B.v,u)/Cross(A.v,B.v);
	return A.P+A.v*t;
}

int HalfPlaneInterSection(Line *L,int n,Point *poly){
	sort(L,L+n);
	Point *p=new Point[n];
	Line *q=new Line[n];
	int head,tail;
	q[head=tail=0]=L[0];
	for(int i=1;i<n;i++){
		while(head<tail && !OnLeft(L[i],p[tail-1]))tail--;
		while(head<tail && !OnLeft(L[i],p[head  ]))head++;
		q[++tail]=L[i];
		if(dcmp(Cross(q[tail].v,q[tail-1].v))==0){
			tail--;
			if(OnLeft(q[tail],L[i].P))q[tail]=L[i];
		}
		p[tail-1]=LineInterSection(q[tail],q[tail-1]);
	}
	while(head<tail && !OnLeft(q[head],p[tail-1]))tail--;
	if(tail-head<=1)return 0;
	p[tail]=LineInterSection(q[tail],q[head]);
	int m=0;
	for(int i=head;i<=tail;i++)poly[++m]=p[i];
	return m;
}

int n,cnt;
Point p[maxn],poly[maxn];
Line L[maxn];
void Init();
int main(){
	freopen("cataclysm.in","r",stdin);
	freopen("cataclysm.out","w",stdout);
    Init();
    return 0;
}
void Init(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)p[i].input();
	sort(p+1,p+n+1);
	for(int i=1;i<n;i++)
		L[cnt++]=Line(p[i],p[i+1]-p[i]);
	L[cnt++]=Line(p[n],Vector(0,1));
	L[cnt++]=Line(p[1],Vector(0,-1));
	L[cnt++]=Line(Point(0,Inf),Vector(-1,0));
	int m=HalfPlaneInterSection(L,cnt,poly);
	Point flyer;flyer.y=Inf;
	for(int i=1;i<=m;i++)
		if(dcmp(poly[i].y-flyer.y)<0)
			flyer=poly[i];
	int i=1,j=1;m--;
	//for(int i=1;i<=m;i++)poly[i].output();
	Point Fire;double ans=Inf;
	//从山脉对应下凸壳
	while(p[i+1].x<poly[1].x)i++;
	for(;i<=n;i++){
		if(p[i].x>poly[m].x)break;
		while(poly[j+1].x<p[i].x)j++;
		Line l1=Line(p[i],Vector(0,1));
		Line l2=Line(poly[j],poly[j+1]-poly[j]);
		Point Inter=LineInterSection(l1,l2);
		//Inter.output();
		double len=Length(Inter-p[i]);
		if(dcmp(len-ans)==-1){
			Fire=Inter;ans=len;
		}
	}
	//从下凸壳对应山脉
	i=1;j=1;
	while(p[i+1].x<poly[1].x)i++;
	for(;j<=m;j++){
		if(p[i].x>poly[m].x)break;
		while(p[i+1].x<poly[j].x)i++;
		Line l1=Line(poly[j],Vector(0,-1));
		Line l2=Line(p[i],p[i+1]-p[i]);
		Point Inter=LineInterSection(l1,l2);
		double len=Length(Inter-poly[j]);
		if(dcmp(len-ans)==-1){
			Fire=poly[j];ans=len;
		}
	}
	printf("%.2lf %.2lf\n",Fire.x,Fire.y);
	printf("%.2lf %.2lf\n",flyer.x,flyer.y);
	//printf("%d\n",m);
}