http://acm.hdu.edu.cn/showproblem.php?pid=4410
(1)由于多边形的边平行于坐标轴,所以n只能是4,6,8。n为4和6的时候只有一种形状。n为8的时候有四种形状:
1)凹形;
2)T行;
3)楼梯行;
4)矩形去掉对角。
他人具体代码:
View Code
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #define int64 __int64 #define INF 1000000000000000 #define EPS 1e-10 #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) using namespace std; inline int DB(double x) { if(x<-EPS) return -1; if(x>EPS) return 1; return 0; } struct vector { double x,y; vector(){} vector(double _x,double _y):x(_x),y(_y){} double operator*(vector a) { return x*a.y-y*a.x; } double operator/(vector a) { return x*a.x+y*a.y; } double length() { return sqrt(x*x+y*y); } //垂直向量 vector vertical() { return vector(-y,x); } //将向量的长度调整为L vector adjust(double L) { double rate=L/length(); return vector(x*rate,y*rate); } //反向量 vector oppose() { return vector(-x,-y); } }; struct point { double x,y; point(){} point(double _x,double _y):x(_x),y(_y){} void get() { scanf("%lf%lf",&x,&y); } vector operator-(point a) { return vector(x-a.x,y-a.y); } point operator+(vector a) { return point(x+a.x,y+a.y); } double dis(point a) { return sqrt((x-a.x)*(x-a.x)+(y-a.y)*(y-a.y)); } }; struct segment { point a,b; segment(){} segment(point _a,point _b):a(_a),b(_b){} void get() { a.get(); b.get(); } //求直线交点(注意是线段所在直线) //前提是直线不能平行 point intersect(segment s) { double s1=(s.a-a)*(s.b-a); double s2=(s.b-b)*(s.a-b); double t=s1+s2; s1/=t;s2/=t; return point(a.x*s2+b.x*s1,a.y*s2+b.y*s1); } //判断两线段是否相交 inline int isintersect(segment s) { double x1=((s.a-a)*(b-a))*((s.b-a)*(b-a)); double x2=((a-s.a)*(s.b-s.a))*((b-s.a)*(s.b-s.a)); return DB(x1)<=0&&DB(x2)<=0; } //求p与线段的垂足 point vertical(point p) { vector t=(b-a).vertical(); return intersect(segment(p,p+t)); } //判断点是否在线段上 int isonsegment(point p) { return DB(min(a.x,b.x)-p.x)<=0&& DB(max(a.x,b.x)-p.x)>=0&& DB(min(a.y,b.y)-p.y)<=0&& DB(max(a.y,b.y)-p.y)>=0; } }; point pt[10]; int n; //返回多边形的有向面积 //逆时针存储返回正,顺时针返回负 double calArea(point pt[],int n) { double s=0; int i; pt[n]=pt[0]; for(i=0;i<n;i++) s+=pt[i].x*pt[i+1].y-pt[i+1].x*pt[i].y; return s/2; } //若为逆时针存储改为顺时针 void init(point pt[],int n) { double s=calArea(pt,n); int i; point temp; if(s>0) { for(i=0;i<n/2;i++) { temp=pt[i]; pt[i]=pt[n-1-i]; pt[n-1-i]=temp; } } } double solve4() { double p=fabs(pt[0].x-pt[2].x); double q=fabs(pt[0].y-pt[2].y); return min(p,q); } double solve6() { int i,k; double temp; for(i=0;i<n;i++) { temp=(pt[i]-pt[(i+n-1)%n])*(pt[(i+1)%n]-pt[i]); if(temp>0) k=i; } point a=pt[k],b=pt[(k+3)%n],c=pt[(k+2)%n],d=pt[(k-2+n)%n]; return min(a.dis(b),min(fabs(c.x-d.x),fabs(c.y-d.y))); } //连续的6个凸 凹形 double deal6(int a,int b) { point p1=pt[(a-2+n)%n],p2=pt[(b+3)%n]; double x=min(fabs(p1.x-p2.x),fabs(p1.y-p2.y)); double y=pt[a].dis(pt[(a-3+n)%n]); double z=pt[b].dis(pt[(b+3)%n]); return min(x,max(y,z)); } //连续的5个凸 楼梯形 double deal5(int a,int b) { point p1=pt[(a-2+n)%n],p2=pt[(b+2)%n]; double x=min(fabs(p1.x-p2.x),fabs(p1.y-p2.y)); double y=pt[a].dis(pt[(a-3+n)%n]); double z=pt[b].dis(pt[(b+3)%n]); return min(x,min(y,z)); } //连续的4个凸 T形 double deal4(int a,int b) { double x=pt[a].dis(pt[(a-3+n)%n]); double y=pt[b].dis(pt[(b+3)%n]); double ans=min(x,y); if(DB(pt[(a-2+n)%n].y-pt[(b+2)%n].y)==0) { x=fabs(pt[(a-1+n)%n].x-pt[(b+1)%n].x); y=fabs(pt[(a-2+n)%n].y-pt[(a+1)%n].y); ans=min(ans,min(x,y)); } else { x=fabs(pt[(a-1+n)%n].y-pt[(b+1)%n].y); y=fabs(pt[(a-2+n)%n].x-pt[(a+1)%n].x); ans=min(ans,min(x,y)); } return ans; } //连续的3个凸 一个矩形缺两个对角 double deal3(int a,int b) { point A,B,C,D,E,F,G,H; A=pt[a]; B=pt[b]; C=pt[(a+1)%n]; D=pt[(a+2)%n]; E=pt[(a+3)%n]; F=pt[(b+1)%n]; G=pt[(b+2)%n]; H=pt[(b+3)%n]; double ans=min(fabs(D.x-G.x),fabs(D.y-G.y)); segment s1,s2,s3,s4; double temp1,temp2; s1=segment(A,E); s2=segment(B,F); s3=segment(B,H); s4=segment(A,C); if(s1.isintersect(s2)) { temp1=min(C.dis(D),C.dis(B)); temp2=min(G.dis(F),A.dis(F));; ans=min(ans,max(temp1,temp2)); } s1=segment(A,F); s2=segment(B,E); s3=segment(B,C); s4=segment(A,H); if(s1.isintersect(s2)) { temp1=min(G.dis(H),H.dis(B)); temp2=min(E.dis(D),A.dis(E)); ans=min(ans,max(temp1,temp2)); } double x=min(A.dis(F),B.dis(H)); double y=min(A.dis(E),B.dis(C)); ans=min(ans,max(x,y)); return ans; } double solve8() { double r[10]; int i; for(i=0;i<n;i++) { r[i]=(pt[i]-pt[(i+n-1)%n])*(pt[(i+1)%n]-pt[i]); } int a,b,s=0,k=0; for(i=0;i<n+n;i++) { if(r[i%n]>0) { s=max(s,k); k=0; if(i<n) a=b,b=i; } else k++; } if(s==3) return deal3(a,b); if(s==4) return deal4(a,b); if(s==5) return deal5(a,b); if(s==6) return deal6(a,b); } int main() { while(scanf("%d",&n),n) { int i; for(i=0;i<n;i++) pt[i].get(); init(pt,n); double ans; if(n==4) ans=solve4(); else if(n==6) ans=solve6(); else ans=solve8(); printf("%.2lf\n",ans); } return 0; }