• 3295. 星际旅行(计算几何)


    题意:n维空间中存在一个超维球,求2点不通过圆(可以经过球表面)的最短距离

    解:两点确定一条直线,3点确定一个平面,有了球心和另外两点就可以确定出一个2维平面,直接以球心为原点,其中一个点为X轴上一点建2维坐标系(这个点的坐标为(它和球心的距离, 0))。之后就是求线段和圆的位置关系了。

    ↓直接从这里借(tou)的图↓

    image

    建完系后得到三点,圆心O和两点AB。三角形AOB面积就是(frac{overrightarrow{OA} imes overrightarrow{OB}}{2}),然后就得到O到AB直线的距离(h = frac{overrightarrow{OA} imes overrightarrow{OB}}{left|AB ight|})

    (h>=R)时,答案就是(left|AB ight|)

    (h<R)时,当ABO或BAO为钝角时(前提两点都在圆外),线段不经过圆,同上;

    否则答案为两条切线+一段弧。

    最后要输出每个点到其他所有点的距离,所以要预处理一下每两点之间的直线距离。

    #include<bits/stdc++.h>
    #define ll long long
    #define pii pair<int,int>
    #define fastio ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
    using namespace std;
    
    const ll mod = 998244353;
    const int maxn = 1e4 + 5;
    
    double pi = acos(-1);
    const double eps = 1e-10;
    
    inline int dcmp(double x)//cmp x with 0
    {
        if (fabs(x) <= eps)return 0;
        return x < 0 ? -1 : 1;
    }
    inline int cmp(double x, double y)
    {
        //x>y return 1
        //x<y reutrn -1
        //x==y return 0
        return dcmp(x - y);
    }
    
    int sgn(double x)
    {
        if (fabs(x) < eps)return 0;
        else return x < 0 ? -1 : 1;
    }
    
    struct Point {
        double x, y;
        Point(double xx, double yy) { x = xx; y = yy; }
        Point operator -(Point s) { return Point(x - s.x, y - s.y); }
        Point operator +(Point s) { return Point(x + s.x, y + s.y); }
        double operator *(Point s) { return x * s.x + y * s.y; }
        Point operator * (double p) { return Point(x * p, y * p); }//向量乘数
        double operator ^(Point s) { return x * s.y - y * s.x; }
        Point operator /(double k) { return Point(x / k, y / k); }
        bool operator ==(Point s) { return sgn(x - s.x) == 0 && sgn(y - s.y) == 0; }
    };
    
    typedef Point Vector;
    
    double Cross(Point a, Point b, Point c)
    {
        return (b - a) ^ (c - a);
    }
    double Cross(Vector A, Vector B) {
        return A.x * B.y - A.y * B.x;
    }
    
    
    double zb[2005][105];//点坐标
    int n, m;
    double dis[2005][2005];//两两之间的直线距离
    
    double get_dis(int x, int y)//返回直线距离
    {
        if (dis[x][y] > eps)return dis[x][y];
        double res = 0;
        for (int i = 1; i <= n; i++)
            res += (zb[x][i] - zb[y][i]) * (zb[x][i] - zb[y][i]);
        return sqrt(res);
    }
    
    
    
    int main()
    {
        fastio;
        cin >> n >> m;
        double r;
        cin >> r;
        for (int i = 1; i <= n; i++)cin >> zb[0][i];
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
            {
                cin >> zb[i][j];
                zb[i][j] -= zb[0][j];//以圆心为原点映射
            }
        for (int j = 1; j <= n; j++)
            zb[0][j] = 0;
        vector<double>ans(m + 1, 0);
        Point O(0, 0);
        for (int i = 0; i <= m; i++)
            for (int j = i + 1; j <= m; j++)
                dis[i][j] = dis[j][i] = get_dis(i, j);
        for (int i = 1; i <= m; i++)
        {
            for (int j = i + 1; j <= m; j++)
            {
                double a = get_dis(0, i);
                double b = get_dis(0, j);
                double c = get_dis(i, j);//三条边距离
                Point A(a, 0);//A点坐标
                double cAOB = (a * a + b * b - c * c) / (2 * a * b);//AOB的cos值
                double AOB = acos(cAOB);//AOB弧度
                Point B(b * cAOB, b * sqrt(1 - cAOB * cAOB));//B点坐标
                double h = Cross(O, A, B) / c;//圆心到直线AB的距离
                if (h >= r || a * a + c * c <= b * b || b * b + c * c <= a * a)//线段AB不经过圆
                {
                    ans[i] += c, ans[j] += c;
                    continue;
                }
                double d1 = sqrt(a * a - r * r);
                double d2 = sqrt(b * b - r * r);//两条切线的长度
                double rad1 = acos(r / a), rad2 = acos(r / b);
                AOB -= rad1 + rad2;//扇形的角度
                double res = d1 + d2 + r * AOB;//两条切线+一段弧
                ans[i] += res, ans[j] += res;
            }
        }
        for (int i = 1; i <= m; i++)
            cout << fixed << setprecision(12) << ans[i] << endl;
        return 0;
    }
    
  • 相关阅读:
    三分
    知识点整合摘取
    Codeforces Round #533 C. Ayoub and Lost Array
    判断当前VC 是push还是present的
    自动布局
    获取当前的 viewController
    UIImageView 点击放大缩小
    UIButton 在UIScrollView里面 点击效果不明显的问题
    IOS AutoLayout 遍历修改约束
    GIT 命令 操作 记录
  • 原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/15260389.html
Copyright © 2020-2023  润新知