坑点:如果输出值的绝对值小于 1e-5 那么结果可能输出 -0.00000 ,需要特判一下。
#include <bits/stdc++.h>
#define ne(i) p[(i+1)%n]
using namespace std;
typedef long long LL;
typedef int lint;
const int maxn = 50001;
const double eps = 1e-12;
const double PI = acos(-1.0);
int sgn(double x)
{
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
struct Point
{
double x,y;
Point(){}
Point(double _x,double _y)
{ x = _x;y = _y;
}
Point operator -(const Point &b)const
{
return Point(x - b.x,y - b.y);
}
//叉积
double operator ^(const Point &b)const
{
return x*b.y - y*b.x; }
//点积
double operator *(const Point &b)const
{
return x*b.x + y*b.y; }
//绕原点旋转角度B(弧度值),后x,y的变化
void transXY(double B)
{
double tx = x,ty = y; x = tx*cos(B) - ty*sin(B);
y = tx*sin(B) + ty*cos(B);
}
};
struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{ s = _s;e = _e;
}
pair<int,Point> operator &(const Line &b)const
{
Point res = s;
if(sgn((s-e)^(b.s-b.e)) == 0)
{
if(sgn((s-b.e)^(b.s-b.e)) == 0)
return make_pair(0,res);//重合
else return make_pair(1,res);//平行
}
double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x += (e.x-s.x)*t;
res.y += (e.y-s.y)*t;
return make_pair(2,res);
}
};
Point PointToLine(Point P,Line L)
{
Point result;
double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s));
result.x = L.s.x + (L.e.x-L.s.x)*t;
result.y = L.s.y + (L.e.y-L.s.y)*t;
return result;
}
double dist(Point a,Point b)
{
return sqrt((a-b)*(a-b));
}
int dist2(Point a,Point b)
{
return (a-b)*(a-b);
}
Point lis[maxn];
int Stack[maxn],top;
//相对于list[0]的极角排序
bool _cmp(Point p1,Point p2)
{
double tmp = (p1-lis[0])^(p2-lis[0]);
if(sgn(tmp) > 0)return true;
else if(sgn(tmp) == 0 && sgn(dist(p1,lis[0]) - dist(p2,lis[0])) <= 0)
return true;
else return false;
}
void Graham(int n)
{
Point p0;
int k = 0;
p0 = lis[0];
//找最下边的一个点
for(int i = 1;i < n;i++)
{
if( (p0.y > lis[i].y) || (p0.y == lis[i].y && p0.x > lis[i].x) )
{
p0 = lis[i];
k = i;
}
}
swap(lis[k],lis[0]);
sort(lis+1,lis+n,_cmp);
if(n == 1)
{
top = 1;
Stack[0] = 0;
return; }
if(n == 2)
{
top = 2;
Stack[0] = 0;
Stack[1] = 1;
return ; }
Stack[0] = 0;
Stack[1] = 1;
top = 2;
for(int i = 2;i < n;i++)
{
while(top > 1 &&sgn((lis[Stack[top-1]]-lis[Stack[top-2]])^(lis[i]-lis[Stack[top-2]])) <=0)
top--;
Stack[top++] = i;
}
}
double ans = 1<<30;
Point ans1,ans2,ans3,ans4;
void rotating_calipers(Point p[],int n)
{
lint cur = 1;
lint cur1 = 1;
lint cur2 = 1;
lint f = 1;
for( lint i = 0;i < n;i++ ){
while( sgn( (ne(cur)-p[cur])^(ne(i)-p[i]) ) <= 0 ) cur = (cur + 1)%n;
while( sgn( (ne(cur1)-p[cur1])*( ne(i)-p[i] ) ) >= 0 ) cur1 = (cur1+1)%n;
if(f){cur2 = cur;f = 0;}
while( sgn( (ne(cur2)-p[cur2])*( ne(i)-p[i] ) < 0 ) ) cur2 = (cur2+1)%n;
double d = dist( p[i],ne(i) );
double s = d + abs((ne(i)-p[i])*(p[cur1]-ne(i))) /d + abs((ne(i)-p[i])*(p[cur2]-p[i])) / d;
Point x = PointToLine( p[cur],Line( ne(i),p[i] ) );
double res = dist( x,p[cur] )*s ;
if( res < ans ){
ans = res;
ans1 = PointToLine(p[cur2],Line( ne(i),p[i] ));
ans2 = PointToLine(p[cur1],Line(ne(i),p[i]));
ans3 = PointToLine(p[cur],Line(p[cur1],ans2));
ans4 = PointToLine( p[cur],Line( ans1,p[cur2] ) );
}
}
return;
}
Point p[maxn];
struct point{
double x,y;
lint id;
point( double xx = 0,double yy = 0,lint iidd = 0 ){
x = xx;
y = yy;
id = iidd;
}
bool operator < ( const point& b )const{
if( y != b.y )
return y < b.y;
else return x < b.x;
}
};
point pp[4];
lint search( ){
pp[0] = point( ans1.x,ans1.y,1 );
pp[1] = point( ans2.x,ans2.y,2 );
pp[2] = point( ans3.x,ans3.y,3 );
pp[3] = point( ans4.x,ans4.y,4 );
sort( pp,pp+4 );
return pp[0].id;
}
int main(){
lint n;
double x,y;
lint tot = 0;
scanf("%d",&n);
for( lint i = 1;i <= n;i++ ){
scanf("%lf%lf",&x,&y);
lis[tot++] = Point( x,y );
}
Graham(n);
for( lint i = 0;i < top;i++ ){
p[i] = lis[Stack[i]];
}
rotating_calipers( p,top );
if( abs( ans ) < 1e-5 ) ans = 0;
printf("%.5lf\n",ans);
lint id = search();
// fflush(stdout);
for( lint i = id,cnt = 0;cnt < 4;cnt++ ){
if( i == 1 ){
if( abs( ans1.x ) < 1e-5 ) ans1.x = 0;
if( abs( ans1.y ) < 1e-5 ) ans1.y = 0;
printf("%.5lf %.5lf\n",ans1.x,ans1.y);
}else if( i == 2 ){
if( abs( ans2.x ) < 1e-5 ) ans2.x = 0;
if( abs( ans2.y ) < 1e-5 ) ans2.y = 0;
printf("%.5lf %.5lf\n",ans2.x,ans2.y);
}else if( i == 3 ){
if( abs( ans3.x ) < 1e-5 ) ans3.x = 0;
if( abs( ans3.y ) < 1e-5 ) ans3.y = 0;
printf("%.5lf %.5lf\n",ans3.x,ans3.y);
}else{
if( abs( ans4.x ) < 1e-5 ) ans4.x = 0;
if( abs( ans4.y ) < 1e-5 ) ans4.y = 0;
printf("%.5lf %.5lf\n",ans4.x,ans4.y);
}
i= i%4+1;
//fflush(stdout);
}
return 0;
}