首页 > 代码库 > hdu 2857 求点关于线段的对称点

hdu 2857 求点关于线段的对称点

本来很简单的一个题,但是有个大坑:

因为模板中Tline用到了直线的一般方程ax+by+c=0,所以有种很坑的情况需要特判:

斜率不存在啊喂

老子坑了一下午2333

 

  1 #include <math.h>  2 #include <stdio.h>  3   4    #define eps 1e-6  5    #define PI acos(-1.0)//3.14159265358979323846  6    //判断一个数是否为0,是则返回true,否则返回false  7    #define zero(x)(((x)>0?(x):-(x))<eps)  8    //返回一个数的符号,正数返回1,负数返回2,否则返回0  9    #define _sign(x)((x)>eps?1:((x)<-eps?2:0)) 10  11   struct point 12   { 13       double x,y; 14       point(){} 15       point(double xx,double yy):x(xx),y(yy) 16       {} 17   }; 18   struct line 19   { 20       point a,b; 21       line(){}      //默认构造函数 22       line(point ax,point bx):a(ax),b(bx) 23       {} 24   };//直线通过的两个点,而不是一般式的三个系数 25   struct TLine 26   { 27       double a,b,c; 28       TLine(){} 29       TLine(double _a,double _b,double _c):a(_a),b(_b),c(_c) 30       {} 31   };//直线一般式的三个系数ax+by+c=0 32   struct TPoint 33   { 34       double x,y; 35       TPoint(){} 36       TPoint(double _x,double _y):x(_x),y(_y) 37       {} 38       TPoint operator-(TPoint&a) 39       { 40           TPoint p1; 41           p1.x=x-a.x; 42           p1.y=y-a.y; 43           return p1; 44       } 45   }; 46  47    //求矢量[p0,p1],[p0,p2]的叉积 48    //p0是顶点 49    //若结果等于0,则这三点共线 50    //若结果大于0,则p0p2在p0p1的逆时针方向 51    //若结果小于0,则p0p2在p0p1的顺时针方向 52    double xmult(point p1,point p2,point p0) 53    { 54        return(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); 55    } 56    //计算dotproduct(P1-P0).(P2-P0) 57    double dmult(point p1,point p2,point p0) 58    { 59        return(p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y); 60    } 61    //两点距离 62    double distance(point p1,point p2) 63    { 64        return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); 65    } 66    //判三点共线 67    int dots_inline(point p1,point p2,point p3) 68    { 69        return zero(xmult(p1,p2,p3)); 70    } 71    //判点是否在线段上,包括端点 72    int dot_online_in(point p,line l) 73    { 74        return zero(xmult(p,l.a,l.b))&&(l.a.x-p.x)*(l.b.x-p.x)<eps&&(l.a.y-p.y)*(l.b.y-p.y)<eps; 75    } 76    //判点是否在线段上,不包括端点 77    int dot_online_ex(point p,line l) 78    { 79        return dot_online_in(p,l)&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y))&&(!zero(p.x-l.b.x)||!zero(p.y-l.b.y)); 80    } 81    //判两点在线段同侧,点在线段上返回0 82    int same_side(point p1,point p2,line l) 83    { 84        return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>eps; 85    } 86    //判两点在线段异侧,点在线段上返回0 87    int opposite_side(point p1,point p2,line l) 88    { 89        return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)<-eps; 90    } 91    //判两直线平行 92    int parallel(line u,line v) 93    { 94        return zero((u.a.x-u.b.x)*(v.a.y-v.b.y)-(v.a.x-v.b.x)*(u.a.y-u.b.y)); 95    } 96    //判两直线垂直 97    int perpendicular(line u,line v) 98    { 99        return zero((u.a.x-u.b.x)*(v.a.x-v.b.x)+(u.a.y-u.b.y)*(v.a.y-v.b.y));100    }101    //判两线段相交,包括端点和部分重合102    int intersect_in(line u,line v)103    {104        if(!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))105            return!same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);106        return dot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u);107    }108    //判两线段相交,不包括端点和部分重合109    int intersect_ex(line u,line v)110    {111        return opposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u);112    }113    //计算两直线交点,注意事先判断直线是否平行!114    //线段交点请另外判线段相交(同时还是要判断是否平行!)115    point intersection(line u,line v)116    {117        point ret=u.a;118        double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));119        ret.x+=(u.b.x-u.a.x)*t;120        ret.y+=(u.b.y-u.a.y)*t;121        return ret;122    }123    /*124    //点到直线上的最近点125    point ptoline(point p,line l)126    {127        point t=p;128        t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;129        return intersection(p,t,l.a,l.b);130   }131   //点到直线距离132   double disptoline(point p,line l)133   {134       return fabs(xmult(p,l.a,l.b))/distance(l.a,l.b);135   }136   //点到线段上的最近点137   point ptoseg(point p,line l)138   {139       point t=p;140       t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;141       if(xmult(l.a,t,p)*xmult(l.b,t,p)>eps)142           return distance(p,l.a)<distance(p,l.b)?l.a:l.b;143       return intersection(p,t,l.a,l.b);144   }145   //点到线段距离146   double disptoseg(point p,line l)147   {148       point t=p;149       t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;150       if(xmult(l.a,t,p)*xmult(l.b,t,p)>eps)151           return distance(p,l.a)<distance(p,l.b)?distance(p,l.a):distance(p,l.b);152       return fabs(xmult(p,l.a,l.b))/distance(l.a,l.b);153   }154   */155   //求p1关于p2的对称点156   TPoint symmetricalPoint(TPoint p1,TPoint p2)157   {158       TPoint p3;159       p3.x=2*p2.x-p1.x;160       p3.y=2*p2.y-p1.y;161       return p3;162   }163   //p点关于直线L的对称点164   TPoint symmetricalPointofLine(TPoint p,TLine L)165   {166       TPoint p2;167       double d;168       d=L.a*L.a+L.b*L.b;169       p2.x=(L.b*L.b*p.x-L.a*L.a*p.x-2*L.a*L.b*p.y-2*L.a*L.c)/d;170       p2.y=(L.a*L.a*p.y-L.b*L.b*p.y-2*L.a*L.b*p.x-2*L.b*L.c)/d;171       return p2;172   }173 174 int main()175 {176     int T;177     double X1,Y1,X2,Y2,Xs,Ys,Xe,Ye;178     scanf("%d",&T);179     while (T--)180     {181         scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&X1,&Y1,&X2,&Y2,&Xs,&Ys,&Xe,&Ye);182         double ta=(Y2-Y1)/(X2-X1),tc=Y2-ta*X2;183         point A,B;184         if (zero(X2-X1))185         {186             A=point(Xs,Ys);187             if (Xe-X1>=0)    B=point(X1-fabs(Xe-X1),Ye);188             else if (Xe-X1<0)    B=point(X1+fabs(Xe-X1),Ye);189         }190         else191         {192             TLine tl=TLine(ta,-1,tc);193             TPoint pt=TPoint(Xe,Ye);194             TPoint tp=symmetricalPointofLine(pt,tl);195 196             A=point(tp.x,tp.y);197             B=point(Xs,Ys);198         }199         line L1=line(A,B);200         line L2=line(point(X1,Y1),point(X2,Y2));201         point ans=intersection(L1,L2);202         if (zero(ans.x)) ans.x=0;203         if (zero(ans.y)) ans.y=0;204         printf("%.3lf %.3lf\n",ans.x,ans.y);205     }206 207     return 0;208 }

 

hdu 2857 求点关于线段的对称点