【题解】Railway [Uva10263]
传送门:( ext{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<algorithm>
#include<cstdio>
#include<cmath>
#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
%.4lf
",ans.x,ans.y);
}
}