本来很简单的一个题,但是有个大坑:
因为模板中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 }