hdu6559 The Tower - 解析几何 - 圆锥

给出一个圆锥的半径,高,一个点的坐标和速度矢量,求最小的时间,使得点到达圆锥上

解析几何就需要取设点

圆心在原点的圆锥,半径为\(r\),高为\(h\)

\[\left\{\begin{array}{l} \frac{h-z}{h}=\frac{R}{r} \\ x^{2}+y^{2}=R^{2} \end{array}\right. \]

再设点的坐标

\[\begin{array}{l} x=x_{0}+v_{x} t \\ y=y_{0}+v_{y} t \\ z=z_{0}+v_{z} t \end{array} \]

然后联立化简得到

\[\left(v_{x}^{2}+v_{y}^{2}-\frac{r^{2} v_{z}^{2}}{h^{2}}\right) t^{2}+2\left(v_{x} x_{0}+v_{y} y_{0}-\frac{z_{0} v_{z} r^{2}}{h^{2}}+\frac{v_{z} r^{2}}{h}\right) t+x_{0}^{2}+y_{0}^{2}-\frac{r^{2}}{h^{2}}\left(h-z_{0}\right)^{2}=0 \]

求得

\[\begin{aligned} t_{1} &=\frac{-b+\sqrt{b^{2}-4 a c}}{2 a} \\ t_{2} &=\frac{-b-\sqrt{b^{2}-4 a c}}{2 a} \end{aligned} \]

最后check一下,这样求出来是两个值,可能直接穿过圆锥面到另一个面,所以得判断一下才行。

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps = 1e-6;
double r, h, x0, y0, z0, vx, vy, vz;
bool check(double tt){
    double x = x0 + vx * tt;
    double y = y0 + vy * tt;
    double z = z0 + vz * tt;
    double R = (h - z) * r / h;
    return (sqrt(x * x + y * y) - R) <= eps;
}
double min(double x, double y) {
    return x > y ? y : x;
}
void solve(int kase) {
    scanf("%lf%lf", &r, &h);
    scanf("%lf%lf%lf", &x0, &y0, &z0);
    scanf("%lf%lf%lf", &vx, &vy, &vz);
    printf("Case %d: ", kase);
    double a = vx * vx + vy * vy - r * r * vz * vz / h / h;
    double b = 2 * (vx * x0 + vy * y0 - z0 * vz * r * r / h / h + vz * r * r / h);
    double c = x0 * x0 + y0 * y0 - r * r / h / h * (h - z0) * (h - z0);
    double t1 = (-b + sqrt(b * b - 4 * a * c)) / (2 * a);
    double t2 = (-b - sqrt(b * b - 4 * a * c)) / (2 * a);
    double ans = 1000000000.0;
    if(check(t1)) {
        ans = min(ans, t1);
    }
    if(check(t2)) {
        ans = min(ans, t2);
    }
    printf("%.7f\n", ans);
}
int main(){
   // freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int t;
    scanf("%d", &t);
    for(int i = 1; i <= t; i++) solve(i);
    return 0;
}
posted @ 2020-09-22 12:15  Emcikem  阅读(173)  评论(0编辑  收藏  举报