时间:2021-07-01 10:21:17 帮助过:18人阅读
题目链接:http://acm.timus.ru/problem.aspx?space=1num=1348 题目的意思是:求一个点到线段的最短距离和最长距离。。 最长距离比较容易,就是求点到线段两个端点较长的那个距离就是ans。 最短距离就比较有意思了。。。 可能的情况就是点到线段的垂线的垂足
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1348
题目的意思是:求一个点到线段的最短距离和最长距离。。
最长距离比较容易,就是求点到线段两个端点较长的那个距离就是ans。
最短距离就比较有意思了。。。
可能的情况就是点到线段的垂线的垂足在线段内,还有就是垂足在线段外。。。
在线段内的话,那么应用叉积求面积+底面长度可以求得垂线长度也就是最短距离。。
如果在线段外的话,最短距离就是点到线段的两个端点的最小值。。
那么问题就来了。。怎么判断垂足在线段内还是在线段外的呢??
详细见代码。 - - 。。。
Code:
- #include <iostream>
- #include
- #include <cstdio>
- #include <cstring>
- #include <cmath>
- using namespace std;
- const double eps = 1e-8;
- const double pi = acos(-1);
- //点
- struct POINT
- {
- double x, y;
- POINT(){ }
- POINT(double a, double b){
- x = a;
- y = b;
- }
- };
- //线段
- struct Seg
- {
- POINT a, b;
- Seg() { }
- Seg(POINT x, POINT y){
- a = x;
- b = y;
- }
- };
- //直线
- struct Line
- {
- POINT a, b;
- Line() {}
- Line(POINT x, POINT y){
- a = x;
- b = y;
- }
- };
- //叉乘
- 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));
- }
- Seg s;
- POINT p;
- double L;
- //点到直线的距离..
- double PointToLine(POINT p, Line l)
- {
- return fabs(cross(p, l.a, l.b)) / dis(l.a, l.b);
- }
- //线段到直线的距离..
- double PointToSeg(POINT p, Seg s)
- {
- POINT tmp = p;
- tmp.x += s.a.y - s.b.y;
- tmp.y += s.b.x - s.a.x;
- if(cross(s.a, p, tmp) * cross(s.b, p, tmp) >= 0){
- return min(dis(p, s.a), dis(p, s.b));
- }
- return PointToLine(p, Line(s.a, s.b));
- }
- void solve()
- {
- double ans1 = PointToSeg(p, s), ans2 = max(dis(p, s.a), dis(p, s.b));
- printf("%.2lf\n%.2lf\n", ans1 > L ? ans1 - L : 0, ans2 > L ? ans2 - L : 0);
- return ;
- }
- int main()
- {
- // freopen("11.txt", "r", stdin);
- while(~scanf("%lf %lf %lf %lf", &s.a.x, &s.a.y, &s.b.x, &s.b.y)){
- scanf("%lf %lf %lf", &p.x, &p.y, &L);
- solve();
- }
- return 0;
- }</cmath></cstring></cstdio></iostream>
好吧,还需要好好的学习。。。