【题解】Railway [Uva10263]

【题解】Railway [Uva10263]

传送门:\(\text{Railway [Uva10263]}\)

【题目描述】

给出点 \(M\) 以及一个由 \(n\) 条线段依次相连的类曲形图(由 \(n+1\) 个点构成),求该“曲形”图中距离点 \(M\) 最近的点 \(P\) 的坐标(\(P\) 可以在任意一条线段上)。

【输入】

输入多组数据,读至 \(EOF\) 结束。

每组数据第一、二行为点 \(M\) 的坐标,接下来一个整数 \(n\) 以及 \(2(n+1)\) 行表示 \(n+1\) 的点的坐标。

【输出】

对于每组数据,输出两行分别表示点 \(P\) 的横、纵坐标。

【样例】

样例输入:
6
-3
3
0
1
5
5
9
-5
15
3
0
0
1
1
0
2
0
样例输出:
7.8966
-2.2414
1.0000
0.0000

【分析】

【计算几何全家桶】

计算几何基础题。

在输入时记录上一个点的坐标,分别求点 \(M\)\(n\) 条线段的最短距离即可。

\((1).\) 求点 \(P\) 到线段 \(AB\) 最短距离:

先判断垂足 \(F\) 的位置,如果在 \(AB\) 的延长线上,则最短距离为 \(PB\),如果在 \(BA\) 的延长线上,则最短距离为 \(PA\),否则为 \(PF\)

\((2).\) 求点 \(P\) 到线段 \(AB\) 的垂足 \(F\)

分别计算 \(AP,BP\)\(AB,BA\) 上的投影并作比,得到 \(AF\)\(AB\) 的比,而 \(AB\) 已知,则可得点 \(AF\),最后再算出 \(F\)

【Code】

#include
#include
#include
#define LD double
#define LL long long
#define Vector Point
#define Re register int
using namespace std;
const int N=1e5+3;
const LD eps=1e-8;
int n;
inline int dcmp(LD a){return a<-eps?-1:(a>eps?1:0);}
inline LD Abs(LD a){return a*dcmp(a);}
struct Point{
    LD x,y;Point(LD X=0,LD Y=0){x=X,y=Y;}
    inline void in(){scanf("%lf%lf",&x,&y);}
}M,P1,P2;
inline LD Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
inline LD Cro(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
inline LD Len(Vector a){return sqrt(Dot(a,a));}
inline LD Angle(Vector a,Vector b){return acos(Dot(a,b)/Len(a)/Len(b));}
inline Point operator+(Point a,Vector b){return Point(a.x+b.x,a.y+b.y);}
inline Vector operator-(Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
inline Vector operator*(Vector a,LD x){return Vector(a.x*x,a.y*x);}
inline bool operator==(Point a,Point b){return !dcmp(a.x-b.x)&&!dcmp(a.y-b.y);}
struct ANS{Point a;LD dis;ANS(Point A,LD D=0){a=A,dis=D;}};
inline Point FootPoint(Point p,Point a,Point b){//点P到直线AB的垂足
    Vector x=p-a,y=p-b,z=b-a;
    LD len1=Dot(x,z)/Len(z),len2=-1.0*Dot(y,z)/Len(z);//分别计算AP,BP在AB,BA上的投影
    return a+z*(len1/(len1+len2));//点A加上向量AF
}
inline Point dis_PL(Point p,Point a,Point b){//点P到线段AB距离
    if(a==b)return a;//AB重合
    Vector x=p-a,y=p-b,z=b-a;
    if(dcmp(Dot(x,z))<0)return a;//P距离A更近
    if(dcmp(Dot(y,z))>0)return b;//P距离B更近
    return FootPoint(p,a,b);//返回垂足
}
int main(){
//  freopen("123.txt","r",stdin);
    while(~scanf("%lf%lf",&M.x,&M.y)){
        scanf("%d",&n),P1.in();
        Point ans=P1;
        while(n--){
            P2.in();Point tmp=dis_PL(M,P1,P2);
            if(dcmp(Len(M-tmp)-Len(M-ans))<0)ans=tmp;
            P1=P2;
        }
        printf("%.4lf\n%.4lf\n",ans.x,ans.y);
    }
}

你可能感兴趣的:(【题解】Railway [Uva10263])