#include<bits/stdc++.h>#definepbpush_back#definedbg(x) cout << #x <<"==="<< x << endlusingnamespace std;constint N =5e4+5;constdouble eps =1e-8;constdouble inf =1e9;constdouble pi =acos(-1.0);intsgn(double x){if(fabs(x)< eps)return0;if(x <0)return-1;elsereturn1;}int n;structPoint{double x, y;Point(double x =0,double y =0):x(x),y(y){}// Point() {}// Point(double _x, double _y) { x = _x; y = _y; }/*
建议用以上形式。
但是注意,不能:
Point(){}
Point(double x,double y){x=x,y=y;}
!今天的所有错误,都来源于Point(double x,double y){x=x,y=y;}这种用法。
Point(double x=0,double y=0):x(x),y(y){}也没有问题,就是不能上面这种
*/voidinput(){scanf("%lf%lf",&x,&y);}booloperator<(const Point &b)const{if(sgn(y - b.y)==0)returnsgn(x - b.x)<0;elsereturnsgn(y - b.y)<0;}
Point operator-(const Point &b)const{returnPoint(x - b.x, y - b.y);}doubleoperator^(const Point &b)const{return x * b.y - b.x * y;}doubleoperator*(const Point &b)const{return x * b.x + y * b.y;}
Point operator*(double k)const{returnPoint(x * k, y * k);}
Point operator+(const Point &b)const{returnPoint(x + b.x, y + b.y);}booloperator==(const Point &b)const{return(sgn(x - b.x))==0&&(sgn(y - b.y)==0);}} a[N];
vector<Point> vp;doubledistance(Point a, Point b){returnsqrt((a.x - b.x)*(a.x - b.x)+(a.y - b.y)*(a.y - b.y));}structcmp{
Point p;cmp(){}cmp(const Point &p0){ p = p0;}//以点p为极坐标原点进行极角排序:sort(,,p.cmp(mi));booloperator()(const Point &a,const Point &b)const{int x =sgn((a - p)^(b - p));if(x ==0)returnsgn(distance(a, p)-distance(b, p))<0;elsereturn x >0;}};//向量ab x 向量acdoublecross(Point a, Point b, Point c){return(b - a)^(c - a);}doubledot(Point a, Point b, Point c){return(b - a)*(c - a);}structpolygon{int n;
Point p[N];} convex;structLine{
Point s, e;Line(){}Line(Point _s, Point _e){ s = _s, e = _e;}//点向式,这里向量可以有很多种表示。Line(Point p,double angle){
s = p;
e = s +Point(cos(angle),sin(angle));}//有向线段(s,e)倾斜角,(-pi,pi)。直线倾斜角只需要将角度转换为(-pi/2,pi/2)即可doubleangle(){double an =atan2(e.y - s.y, e.x - s.x);// atan(double)返回值域为(-pi/2,pi/2)// atan2(y,x)返回值域为(-pi,pi)return an;}};//由a数组求凸包传给 P ———— 没想到求凸包这么简单,之前想得太难了,艹voidgetconvex(Point *a,int n, polygon &convex){
Point mi = a[0];for(int i =1; i < n; i++) mi =min(mi, a[i]);sort(a, a + n,cmp(mi));//排序:求凸包的准备工作(这里不是极角排序)int top =0;// top模拟栈顶
convex.p[top]= a[0];
convex.p[++top]= a[1];for(int i =2; i < n; i++){while(top >0&&(sgn(cross(convex.p[top -1], convex.p[top], a[i]))<=0))
top--;
convex.p[++top]= a[i];}
convex.n = top +1;}//点到直线距离,注意加绝对值。doubledispointtoline(Point a, Line b){
Point s = b.s, e = b.e;returnfabs(cross(s, e, a))/distance(s, e);}//点在直线上的投影
Point progpointtoline(Point a, Line b){
Point s = b.s, e = b.e;// dot不是cross,有找了一天的错。百炼成钢double k =dot(s, e, a)/distance(s, e)/distance(s, e);return s +(e - s)* k;}//调用凸包的p和ndoublegetminrectanglecover(Point *a,int n){if(n <3)return0.0;double res = inf;int r1 =1, r2 =1, r3 =1;
a[n]= a[0];for(int i =0; i < n; i++){//卡逆时针第1,2,3个点a[r1],a[r2],a[r3]//注意别取等while(sgn((a[i +1]- a[i])*(a[r1 +1]- a[r1]))>0)
r1 =(r1 +1)% n;while(sgn(cross(a[i], a[i +1], a[r2 +1])-cross(a[i], a[i +1], a[r2]))>=0)
r2 =(r2 +1)% n;if(i ==0) r3 = r2;//绝活while(sgn((a[i +1]- a[i])*(a[r3 +1]- a[r3]))<0)
r3 =(r3 +1)% n;//! 1.更新
Line li =Line(a[i], a[i +1]);double area =dispointtoline(a[r2], li)*distance(progpointtoline(a[r1], li),progpointtoline(a[r3], li));if(sgn(area - res)<0){
res = area;
vp.clear();//! 3.操作点
vp.pb(progpointtoline(a[r1], li));
vp.pb(progpointtoline(a[r3], li));
Line lii =Line(a[r2], li.angle());
vp.pb(progpointtoline(a[r1], lii));
vp.pb(progpointtoline(a[r3], lii));
Point mi = vp[0];for(auto i : vp) mi =min(mi, i);sort(vp.begin(), vp.end(),cmp(mi));}}//打印printf("%.5lf\n", res);for(auto i : vp){if(sgn(i.x - eps)<=0) i.x =0;if(sgn(i.y - eps)<=0) i.y =0;printf("%.5lf %.5lf\n", i.x, i.y);}//!返回值return res;}signedmain(){
cin >> n;for(int i =0; i < n; i++) a[i].input();getconvex(a, n, convex);getminrectanglecover(convex.p, convex.n);return0;}/*
input:::
6 1.0 3.00000
1 4.00000
2.0000 1
3 0.0000
3.00000 6
6.0 3.0
output:::
18.00000
3.00000 0.00000
6.00000 3.00000
3.00000 6.00000
0.00000 3.00000
*/