蓝桥杯 还有多远才能见到你

题意

如果我们之间的距离是一千步,我会向你走出九百九十九步,只要你向我的方向迈出最后的一步。后来,我朝你的方向走了一千步,我却不知道你在哪里。
(写题写出了网抑云...)
给定\(n,m\)个点 , 分别代表两个折线段 , 求其中折线段相距最近的距离

思路

第一次做计算几何的题

点到线段的距离

利用点积可以判断垂足是否在线段内 , 否则判断到两个端点距离的最小值即可

线段到线段的最短距离

相交为0
否则 , 最短距离即四个点到另一条线段的距离的最小值

考虑一些计算几何的基础知识
0. sg : 通过与eps比较来判断正负零

  1. 读取double , 不要用read
  2. 减号的重载
struct Point
{
double x,y;
operaotr-(const Point& other){
return {x-other.x,y-other.y};
}
}
  1. 距离 , 点积 , 叉积
double distance(Point x,Point y)
{ }//略
double Dot(Point a,Point b)
{
return a.x * b.x + a.y * b.y;//用于判断夹角
}
double Cross(Point a,Point b)
{
  return a.x * b.y - a.y * b.x;//判断是否相交 , 或者用于计算垂线长度
}

  1. 判断相交
bool xj(P a,P b,P c,P d)
{
double c1 = Cross(b-a,c-a),c2=Cross(b-a,d-a);
double d1 = Cross(a-c,d-c),d2=Cross(b-c,d-c);
return sg(c1) * sg(c2) < 0 && sg(d1) * sg(c2) < 0;
}

  1. 求点到线长度
double getlen(P p,P a,P b)
{
  return fabs(Cross(p-a,a-b))/Distance(a,b);
}

代码

#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
struct Point {
    double x,y;
    Point operator-(const Point &a) {
        return {x-a.x,y-a.y};
    }
};
double Distance(Point a,Point b) {
    return sqrt((a.x-b.x) * (a.x -b.x) + (a.y - b.y) * (a.y - b.y));
}
double Dot(Point a,Point b) {
    return a.x * b.x + a.y * b.y;
}
double Cross(Point a,Point b) {
    return a.x * b.y - a.y * b.x;
}
double sg(double x) {
    if (x > eps) return 1;
    if (x<-eps) return -1;
    return 0;
}
double xj(Point a,Point b,Point c,Point d) {
    double c1 = Cross(b-a,c-a),c2 = Cross(b-a,d-a);
    double d1 = Cross(d-c,a-c),d2 = Cross(d-c,b-c);
    return sg(c1) * sg(c2) < 0 && sg(d1) * sg(d2) < 0;
}

double getlen(Point p,Point a,Point b) {
    return fabs(Cross(p-a,a-b))/Distance(a,b);
}
double f(Point p,Point a,Point b) {
    if (Dot(p-a,b-a) < 0 || Dot(p-b,a-b)<0) {
        return min(Distance(p,a),Distance(p,b));
    }
    return getlen(p,a,b);
}

int main() {
    int n,m;
    cin>>n>>m;
    vector<Point> a(n),b(m);
    for (int i = 0; i< n; i++) {
        cin>>a[i].x>>a[i].y;

    }
    for (int i = 0; i< m; i++) {
        cin>>b[i].x>>b[i].y;
    }
    double ans = 2e18+7;
    for (int i = 1; i< n; i++) {
        for (int j = 1; j< m; j++) {
            if (xj(a[i],a[i-1],b[j],b[j-1])) {
                ans = 0;
                break;
            }
            ans = min({ans,
            f(a[i],b[j],b[j-1]),
                f(a[i-1],b[j],b[j-1]),
                f(b[j],a[i],a[i-1]),
                f(b[j-1],a[i],a[i-1])
            });
        }
    }
    cout<<fixed<<setprecision(3)<<ans<<"\n";

    return 0;
}

posted @ 2025-06-01 13:33  Guaninf  阅读(16)  评论(0)    收藏  举报