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 }
原文地址:https://www.cnblogs.com/proverbs/p/2924729.html