码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2021-03-30 13:32:19      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:flag   clu   alpha   ack   efi   一个   def   roo   vector   

[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();
}

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

标签:flag   clu   alpha   ack   efi   一个   def   roo   vector   

原文地址:https://www.cnblogs.com/mollnn/p/14591205.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!