zoukankan      html  css  js  c++  java
  • [ICPC2018西安F] Interstellar … Fantasy

    [ICPC2018西安F] Interstellar … Fantasy - 几何

    Description

    有一个球是障碍物不能走,给你两个点,从起点到终点的最短路程是多少

    Solution

    求出切线,于是路径为两条直线加一个弧段

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    vector<double> solve_equ(double a, double b, double c)
    {
        double delta = b * b - 4 * a * c;
        if (delta < 0)
            return {};
        double sqrt_delta = sqrt(delta + 1e-10);
        return {(-b + sqrt_delta) / a / 2, (-b - sqrt_delta) / a / 2};
    }
    
    struct vec3
    {
        double x, y, z;
        void read()
        {
            cin >> x >> y >> z;
        }
        vec3 operator+(const vec3 &rhs)
        {
            return {x + rhs.x, y + rhs.y, z + rhs.z};
        }
        vec3 operator-(const vec3 &rhs)
        {
            return {x - rhs.x, y - rhs.y, z - rhs.z};
        }
        double operator*(const vec3 &rhs)
        {
            return x * rhs.x + y * rhs.y + z * rhs.z;
        }
        vec3 operator*(const double &rhs)
        {
            return {x * rhs, y * rhs, z * rhs};
        }
        double dist(const vec3 &rhs)
        {
            return sqrt((*this - rhs) * (*this - rhs));
        }
    };
    
    void solve()
    {
        vec3 o, s, t, d;
        o.read();
        double r;
        cin >> r;
        s.read();
        t.read();
        d = t - s;
        double a = d * d;
        double b = d * (s - o) * 2;
        double c = (s - o) * (s - o) - r * r;
        auto roots = solve_equ(a, b, c);
        int flag = (s.dist(o) >= r) || (t.dist(o) >= r);
        double x = o.dist(s);
        double y = o.dist(t);
        double z = s.dist(t);
        double p = (x + y + z) / 2;
        double h = sqrt(p * (p - x) * (p - y) * (p - z)) * 2 / z;
        if (x * x >= y * y + z * z || y * y >= x * x + z * z || h >= r)
        {
            cout << fixed << setprecision(10) << s.dist(t) << endl;
        }
        else
        {
            vector<vec3> hit_points;
            for (auto i : roots)
            {
                hit_points.push_back(s + d * i);
            }
            double l = hit_points[0].dist(hit_points[1]);
    
            double alpha = acos(r / x);
            double belta = acos(r / y);
            double gamma = acos((x * x + y * y - z * z) / 2 / x / y);
            double theta = gamma - alpha - belta;
            double ans = r * theta + sqrt(x * x - r * r) + sqrt(y * y - r * r);
            cout << fixed << setprecision(10) << ans << endl;
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        int t;
        cin >> t;
        while (t--)
            solve();
    }
    
  • 相关阅读:
    Map使用总结
    AutoReleasePool使用总结
    UIImage使用总结
    Subversion简明手册--使用hook svn
    转:MyEclipse8.6插件安装方法
    转:myeclipse 8.x 插件安装方法终极总结
    如何通过类找到对应的jar包
    关于更改MYECLIPSE JS 代码背景颜色
    win7 64位系统下 PL/SQL无法连接的问题
    Windows7(x64)下Oracle10g安装
  • 原文地址:https://www.cnblogs.com/mollnn/p/14591205.html
Copyright © 2011-2022 走看看