【题解】
先求出这些点的凸包
可以证明,最小的矩形一定与凸包的边有重叠注意这样的写法:Cross(ch[q+1]-ch[i+1],ch[i]-ch[i+1]) - Cross(ch[q]-ch[i+1],ch[i]-ch[i+1]) >-eps (不过写成 >0 也能AC。。。)
【代码】
#include<stdio.h> #include<stdlib.h> #include<math.h> #define eps 1e-10 struct Point { double x,y; Point() { x=y=0; } }; typedef Point Vector; Point P[50005],ch[50005],Q[5]; Vector operator + (Vector a,Vector b) { a.x+=b.x; a.y+=b.y; return a; } Vector operator - (Vector a,Vector b) { a.x-=b.x; a.y-=b.y; return a; } Vector operator * (Vector a,double b) { a.x*=b; a.y*=b; return a; } bool operator < (Point a,Point b) { return a.x<b.x || ( a.x==b.x && a.y<b.y ); } bool operator > (Point a,Point b) { return a.x>b.x || ( a.x==b.x && a.y>b.y ); } int dcmp(double x) { if(x<=eps&&x>=-eps) return 0; if(x>0) return 1; return -1; } double Dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; } double Cross(Vector a,Vector b) { return a.x*b.y-b.x*a.y; } double Length(Vector a) { return sqrt(a.x*a.x+a.y*a.y); } double dis(Point p,Point a,Point b) { return fabs(Cross(p-a,b-a))/Length(a-b); } Vector xz(Vector a) { Vector b; b.x=-a.y; b.y=a.x; return b; } Point jiaodian(Point P,Vector v,Point Q,Vector w) { Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return P+v*t; } void kp(int low,int high) { int i=low,j=high; Point mid=P[(i+j)/2],t; while(i<j) { while(P[i]<mid) i++; while(P[j]>mid) j--; if(i<=j) { t=P[i]; P[i]=P[j]; P[j]=t; i++; j--; } } if(j>low) kp(low,j); if(i<high) kp(i,high); } int main() { Vector t; double ans=-1.0,D,H,L,R; int n,i,j=1,k,cnt=0,q=2,l,r=2; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%lf%lf",&P[i].x,&P[i].y); kp(1,n); for(i=1;i<=n;i++) { while( cnt>1 && dcmp( Cross(ch[cnt]-ch[cnt-1],P[i]-ch[cnt-1]) )<=0 ) cnt--; ch[++cnt]=P[i]; } k=cnt; for(i=n-1;i>=1;i--) { while( cnt>k && dcmp( Cross(ch[cnt]-ch[cnt-1],P[i]-ch[cnt-1]) )<=0 ) cnt--; ch[++cnt]=P[i]; } //printf("(%.2lf,%.2lf) ",ch[i].x,ch[i].y); for(i=1;i<cnt;i++) { D=Length(ch[i]-ch[i+1]); while( Cross(ch[q+1]-ch[i+1],ch[i]-ch[i+1]) - Cross(ch[q]-ch[i+1],ch[i]-ch[i+1]) > -eps ) q=q%(cnt-1)+1; while( Dot(ch[r+1]-ch[i+1],ch[i]-ch[i+1]) - Dot(ch[r]-ch[i+1],ch[i]-ch[i+1]) < eps ) r=r%(cnt-1)+1; if(i==1) l=r;//否则l无法迈出"第一步" while( Dot(ch[l+1]-ch[i+1],ch[i]-ch[i+1]) - Dot(ch[l]-ch[i+1],ch[i]-ch[i+1]) > -eps ) l=l%(cnt-1)+1; H=dis(ch[q],ch[i],ch[i+1]); L=Dot(ch[l]-ch[i+1],ch[i]-ch[i+1])/D; R=-Dot(ch[r]-ch[i+1],ch[i]-ch[i+1])/D; if(ans==-1||ans>H*(L+R)) { ans=H*(L+R); t=xz(ch[i+1]-ch[i]); Q[1]=(ch[i]-ch[i+1])*(L/D)+ch[i+1];//从左下开始 Vector e=(ch[i]-ch[i+1])*((D+L)/D); Q[2]=(ch[i+1]-ch[i])*((D+R)/D)+ch[i]; Q[3]=jiaodian(ch[r],t,ch[q],ch[i+1]-ch[i]); Q[4]=jiaodian(ch[l],t,ch[q],ch[i+1]-ch[i]); } } printf("%.5lf\n",ans); for(i=2;i<=4;i++) if( Q[i].y<Q[j].y || (Q[i].y==Q[j].y&&Q[i].x<Q[j].x) ) j=i; for(i=0;i<4;i++) printf("%.5lf %.5lf\n",Q[(j+i-1)%4+1].x,Q[(j+i-1)%4+1].y); return 0; }