【题目链接】:​​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
*/