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         else
191         {
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
",ans.x,ans.y);
205     }
206 
207     return 0;
208 }
原文地址:https://www.cnblogs.com/pdev/p/4160490.html