URAL 1348 求垂足
题意:
就是求点到线段的最短和最长距离。如果最短距离比L大,输出L - MIN 否则输出0。最长距离也是。
题解:
利用坐标旋转+向量的点积求投影向量从而得到垂足。这样做的精度远远高于解析几何方法,而且不用考虑任何边界情况~
ym applepi!!~
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <cstdio> 6 #include <cmath> 7 8 #define PI 3.14159265358979 9 #define EPS 1e-4 10 11 using namespace std; 12 13 struct PO 14 { 15 double x,y; 16 }; 17 18 struct LI 19 { 20 PO a,b; 21 }li[5]; 22 23 double len; 24 25 inline void read() 26 { 27 scanf("%lf%lf%lf%lf%lf%lf%lf",&li[1].a.x,&li[1].a.y,&li[1].b.x,&li[1].b.y,&li[2].a.x,&li[2].a.y,&len); 28 } 29 30 inline int doublecmp(double x) 31 { 32 if(x>EPS) return 1; 33 else if(x<-EPS) return -1; 34 return 0; 35 } 36 37 inline double dot(PO &a,PO &b,PO &c) 38 { 39 return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y); 40 } 41 42 inline double cross(PO &a,PO &b,PO &c) 43 { 44 return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); 45 } 46 47 inline double getlen(PO &a)//向量的模 48 { 49 return sqrt(a.x*a.x+a.y*a.y); 50 } 51 52 inline double getdis(PO &a,PO &b) 53 { 54 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 55 } 56 57 inline PO getty(PO b,PO a)//投影向量 58 { 59 PO res=a; 60 double k=dot(li[0].a,a,b)/(getlen(a)*getlen(a)); 61 res.x*=k; res.y*=k; 62 return res; 63 } 64 65 inline PO rotate(PO a,double hd)//旋转 66 { 67 PO c; 68 c.x=a.x*cos(hd)-a.y*sin(hd); 69 c.y=a.x*sin(hd)+a.y*cos(hd); 70 return c; 71 } 72 73 inline void go() 74 { 75 if(doublecmp(cross(li[1].a,li[1].b,li[2].a))==0)//在线段所在直线上 76 { 77 if(doublecmp(dot(li[2].a,li[1].a,li[1].b))<=0)//在线段上 78 { 79 puts("0.00"); 80 printf("%.2f\n",max(0.0,max(getdis(li[1].a,li[2].a),getdis(li[1].b,li[2].a))-len)); 81 } 82 else 83 { 84 double a=getdis(li[1].a,li[2].a)-len; 85 double b=getdis(li[1].b,li[2].a)-len; 86 if(a>b) swap(a,b); 87 printf("%.2f\n%.2f\n",max(a,0.0),max(b,0.0)); 88 } 89 } 90 else 91 { 92 li[2].b.x=li[1].b.x-li[1].a.x; 93 li[2].b.y=li[1].b.y-li[1].a.y; 94 li[2].b=rotate(li[2].b,-PI*0.5); 95 PO s=li[1].b; 96 s.x-=li[2].a.x; 97 s.y-=li[2].a.y; 98 PO ty=getty(s,li[2].b); 99 PO t; 100 t.x=li[2].a.x+ty.x; 101 t.y=li[2].a.y+ty.y; 102 if(doublecmp(dot(t,li[1].a,li[1].b))<=0)//垂足在线段上 103 { 104 printf("%.2lf\n",max(0.0,getlen(ty)-len)); 105 printf("%.2lf\n",max(0.0,max(getdis(li[1].a,li[2].a),getdis(li[1].b,li[2].a))-len)); 106 } 107 else 108 { 109 double a=getdis(li[1].a,li[2].a)-len; 110 double b=getdis(li[1].b,li[2].a)-len; 111 if(a>b) swap(a,b); 112 printf("%.2lf\n%.2lf\n",max(a,0.0),max(b,0.0)); 113 } 114 } 115 } 116 117 int main() 118 { 119 read(),go(); 120 return 0; 121 }
没有人能阻止我前进的步伐,除了我自己!