【题目链接】:click here~~
【题目大意】:求某点到一条线段的最小距离与最大距离。
【思路】:
分析可知,最大距离一定在端点处取得。那么接下来求最小距离时,先求出垂线与线段所在直线的交点,然后判断交点在不在线段上。如果在,则最小距离为垂线段的距离,即交点到此点的距离。如果不在,则最小距离必在另一端点取得。问题转换如何判断点与线段的垂足是否在线段上,可以利用叉积方便的求出。
代码:
/* * Problem: NO:URAL 1348 * Running time: 1MS * Complier: G++ * Author: herongwei * Create Time: 20:00 2015/10/4 星期日 */ #include <math.h> #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> typedef long long LL; using namespace std; #define min(a,b) a<b?a:b #define max(a,b) a>b?a:b const double eps=1e-8; const double pi=acos(-1.0); int sgn(double x) { if(fabs(x) < eps)return 0; if(x < 0)return -1; else return 1; } struct POINT //点 { double x,y; POINT(){} POINT(double _x ,double _y) { x = _x; y = _y; } POINT operator -(const POINT &b)const { return POINT(x - b.x, y - b.y); } double operator ^(const POINT &b)const { return x*b.y - y*b.x; } }; struct Seg //线段 { POINT s,e; Seg(){} Seg(POINT _s,POINT _e) { s=_s; e=_e; } }; struct Line//直线 { POINT s,e; Line(){} Line(POINT _s,POINT _e) { s=_s; e=_e; } }; //叉乘 double cross(POINT o, POINT a, POINT b) { return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y); } //求两点间的距离 double dis(POINT a, POINT b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } // 点到直线的距离,叉积求面积/底面长度得垂线长度 double Point_to_Line(POINT p,Line l) { return fabs(cross(p,l.s,l.e)) / dis(l.s,l.e); } // 点到线段的距离 double Point_to_Seg(POINT p,Seg s) { POINT tmp=p; tmp.x += s.s.y-s.e.y; tmp.y += s.e.x-s.s.x; if(cross(s.s, p, tmp) * cross(s.e, p, tmp) >= 0) /// 叉积判断垂足是否在线段上 { return min(dis(p, s.s), dis(p, s.e)); } return Point_to_Line(p, Line(s.s, s.e));///垂足在线段上 } Seg s; POINT p; double L; void solve() { double ans1=Point_to_Seg(p,s),ans2=max(dis(p,s.s),dis(p,s.e)); ans1=ans1>L?ans1-L:0,ans2=ans2>L?ans2-L:0; printf("%.2f\n%.2f\n",ans1,ans2); } int main() { while(cin>>s.s.x>>s.s.y>>s.e.x>>s.e.y) { cin>>p.x>>p.y>>L;solve(); } return 0; } /* input output 8 -6 8 6 0 0 7 1.00 3.00 */