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;
}
I‘m Stein, welcome to my blog