hdu4410(Boomerang)(计算几何)

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;
 }

 

转载于:https://www.cnblogs.com/tim11/archive/2012/10/27/2742972.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值