#include"string.h" #include"stdio.h" #include"iostream" #include"algorithm" #include"queue" #include"stack" #define M 100009 #define N 100009 #include"stdlib.h" #include"math.h" #define inf 10000000000000000LL #define INF 0x3f3f3f3f #define PI acos(-1.0) #define eps 1e-10 using namespace std; struct node { double x,y; node(){} node(double _x,double _y):x(_x),y(_y){} node operator +(node p)//向量加法 { return node(x+p.x,y+p.y); } node operator -(node p)//向量减法 { return node(x-p.x,y-p.y); } double operator *(node p)//向量叉乘 { return x*p.y-y*p.x; } double operator ^(node p)//向量点乘 { return x*p.x+y*p.y; } node operator /(double p)//向量除法 { return node(x/p,y/p); } node operator *(double p)//向量乘法 { return node(x*p,y*p); } }p[M],q[M]; int cnt,n; double max(double x,double y) { return x>y?x:y; } double min(double x,double y) { return x<y?x:y; } double cross(node a,node b,node c)//叉积 { return (b-a)*(c-a); } double dot(node a,node b,node c)//点积 { return (b-a)^(c-a); } double len(node a)//向量长吨 { return sqrt(a^a); } double dis(node a,node b)//两点距离 { return len(b-a); } int cmp(node a,node b)//极角排序 { double temp=cross(p[0],a,b);//逆时针排序 if(temp>0) return 1; else if(fabs(temp)<eps&&dis(p[0],a)<dis(p[0],b))//角度相同则按照距离排序 return 1; else return 0; } void input(int n)//输入 { for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); } void sort_point(int n)//凸包点集的输入即排序 { int i,k; node start; start=p[0]; k=0; for(i=1;i<n;i++) { if((start.y>p[i].y)||(fabs(start.y-p[i].y)<eps&&start.x>p[i].x)) { start=p[i]; k=i; } } p[k]=p[0]; p[0]=start; sort(p+1,p+n,cmp); } void be_weight(int val) { int temp=val; n=1; for(int i=1;i<temp;i++) { if(fabs(p[i-1].x-p[i].x)<eps&&fabs(p[i-1].y-p[i].y)<eps) continue; p[n++]=p[i]; } } void Convex_hull(int n)//求凸包凸包上的点存在q中 { int i; if(n==1) { q[0]=p[0]; cnt=1; } else if(n==2) { q[0]=p[0]; q[1]=p[1]; q[2]=p[0]; cnt=2; } else if(n>=3) { q[0]=p[n-1]; q[1]=p[0]; q[2]=p[1]; cnt=2; for(i=2;i<n;i++) { while(cross(q[cnt-1],q[cnt],p[i])<0) cnt--; q[++cnt]=p[i]; } } } double Perimeter(int cnt)//凸包周长 { double sum=0; for(int i=1;i<=cnt;i++) sum+=dis(q[i-1],q[i]); return sum; } double Area(int cnt)//凸包面积 { double sum=0; node p(0,0); for(int i=1;i<=cnt;i++) sum+=cross(p,q[i-1],q[i]); return fabs(sum/2.0); } node barycenter_cur(int n)//原多边形的重心 { double sum=0; node ret(0.0,0.0); for(int i=2;i<n;i++) { double area=cross(p[0],p[i-1],p[i]); sum+=area; ret=ret+(p[0]+p[i-1]+p[i])/3.0*area; } ret=ret/sum; return ret; } node barycenter_now(int cnt)//凸包的重心 { double sum=0; node ret(0.0,0.0); for(int i=2;i<cnt;i++) { double area=cross(q[0],q[i-1],q[i]); sum+=area; ret=ret+(q[0]+q[i-1]+q[i])/3.0*area; } ret=ret/sum; return ret; } double Diameter(int cnt)//旋转卡壳法求凸包的直径即最大的点对距离 { double maxi=0; int j=1; for(int i=1;i<=cnt;i++) { while(fabs(cross(q[i-1],q[i],q[(j+1)%cnt]))>fabs(cross(q[i-1],q[i],q[j%cnt]))) j++; maxi=max(maxi,dis(q[i-1],q[j%cnt])); maxi=max(maxi,dis(q[i],q[j%cnt])); } return maxi; } double Max_triangle(int cnt)//旋转卡壳法求面积最大的三角形 { double maxi=0; int j=1; int k=1; for(int i=1;i<=cnt;i++) { while(fabs(cross(q[i-1],q[j%cnt],q[(k+1)%cnt]))>fabs(cross(q[i-1],q[j%cnt],q[k%cnt]))) k++; maxi=max(maxi,fabs(cross(q[i-1],q[j%cnt],q[k%cnt]))); while(fabs(cross(q[i-1],q[(j+1)%cnt],q[k%cnt]))>fabs(cross(q[i-1],q[j%cnt],q[k%cnt]))) j++; maxi=max(maxi,fabs(cross(q[i-1],q[j%cnt],q[k%cnt]))); } return maxi/2.0; /*其思路是这样的,定点I,p,q,先I,p固定,让q旋转找到最大的面积三角形,之后,I,q固定,p旋转, 找到最大的三角形面积,比较记录.然后i++;直到i遍历所有顶点.所求出来的三角形就是面积 最大.这里的旋转卡壳思想就是固定,旋转.这样的.显然i++后,p,q两点不需要再从i+1,i+2开始,这 个好形容,对p,q进行取模运算的时候,注意自己的SP栈指针多大.*/ } void Min_rectangle(int cnt)//旋转卡壳法求面积和周长最小的环绕矩形 { if(cnt<=2)//输出时注意的地方***** { if(cnt==1) printf("%.2lf %.2lf ",0.0,0.0); else printf("%.2lf %.2lf ",0.0,2*dis(p[0],p[1])); return; } double S=inf,C=inf; int j,k,r; double h,w; j=k=r=1; for(int i=1;i<=cnt;i++) { double L=dis(q[i-1],q[i]); while(fabs(cross(q[i-1],q[i],q[(j+1)%cnt]))>fabs(cross(q[i-1],q[i],q[j%cnt]))) j++; h=fabs(cross(q[i-1],q[i],q[j%cnt]))/L; while(dot(q[i-1],q[i],q[(k+1)%cnt])>dot(q[i-1],q[i],q[k%cnt])) k++; if(i==1) r=k; while(dot(q[i-1],q[i],q[(r+1)%cnt])<=dot(q[i-1],q[i],q[r%cnt])) r++; w=(dot(q[i-1],q[i],q[k%cnt])-dot(q[i-1],q[i],q[r%cnt]))/L; S=min(S,w*h); C=min(C,(w+h)*2); } printf("%.2lf ",S);//输出时注意的地方***** printf("%.2lf ",C); } int main() { while(scanf("%d",&n),n) { input(n);//输入 sort_point(n);//极角排序 be_weight(n);//去重 Convex_hull(n);//求凸包 Min_rectangle(cnt); } return 0; }