The Tower
Problem Description
The Tower shows a tall tower perched on the top of a rocky mountain. Lightning strikes, setting the building alight, and two people leap from the windows, head first and arms outstretched. It is a scene of chaos and destruction.
There is a cone tower with base center at (0, 0, 0), base radius r and apex (0, 0, h). At time 0 , a point located at (x0, y0, z0) with velocity (vx, vy, vz). What time will they collide? Here is the cone tower.
Input
The first line contains testcase number T (T ≤ 1000), For each testcase the first line contains spaceseparated real numbers r and h (1 ≤ r, h ≤ 1000) — the base radius and the cone height correspondingly.
For each testcase the second line contains three real numbers x0, y0, z0 (0 ≤ |x0|, |y0|, z0 ≤ 1000). For each testcase the third line contains three real numbers vx, vy, vz (1 ≤ v2x + v2y + v2z ≤ 3 × 106). It is guaranteed that at time 0 the point is outside the cone and they will always collide.
Output
For each testcase print Case i : and then print the answer in one line, with absolute or relative error not exceeding 10−6
Sample Input
2
1 2
1 1 1
-1.5 -1.5 -0.5
1 1
1 1 1
-1 -1 -1
Sample Output
Case 1: 0.3855293381
Case 2: 0.5857864376
题意
给出一个圆锥,底面圆心在原点,给出圆锥外一点(保证为圆锥外一点)。并给出该点在各个方向上的移动速度。求点撞击在圆锥面上时的时间t
题解
首先看了很久题,无法将其转化到平面通过几何方式求取(也可能是我想不到),所以只能通过解析几何的方式,通过方程求取。
由底面方程
x
2
+
y
2
=
r
2
x^2+y^2=r^2
x2+y2=r2和截面所做三角形
根据相似三角形,求出
r
′
=
r
(
h
−
z
)
h
r'=\cfrac{r(h-z)}{h}
r′=hr(h−z)
故圆锥面方程为
x
2
+
y
2
=
r
′
2
=
r
2
(
h
−
z
)
2
h
2
,
z
∈
[
0
,
h
]
x^2+y^2=r'^2=\cfrac{r^2(h-z)^2}{h^2},z\in[0,h]
x2+y2=r′2=h2r2(h−z)2,z∈[0,h]
由给出的点坐标
(
x
0
,
y
0
,
z
0
)
(x_0,y_0,z_0)
(x0,y0,z0)以及对应方向运动速度
(
v
x
,
v
y
,
v
z
)
(v_x,v_y,v_z)
(vx,vy,vz)
我们设撞击时间为t
因此撞击点坐标为
(
x
0
+
v
x
t
,
y
0
+
v
y
t
,
z
0
+
v
z
t
)
(x_0+v_xt,y_0+v_yt,z_0+v_zt)
(x0+vxt,y0+vyt,z0+vzt)
将撞击点坐标带入圆锥面方程,得到一个只关于t的一元二次方程,太长了,恶心,不往上打了。
根据方程解出t的值
t
1
,
t
2
(
t
1
<
t
2
)
t_1,t_2(t_1<t_2)
t1,t2(t1<t2)
要注意的是,我们写出的圆锥方程是
z
∈
[
0
,
h
]
z\in[0,h]
z∈[0,h]的,而在程序中没有表示所以是上下两个圆锥底对底拼在一起的,因此我们得到两个撞击点。
因为保证了撞击点是存在的,所以我们只需要判断,t1时的撞击点是否满足
t
1
>
0
且
z
0
+
v
z
t
1
∈
[
0
,
h
]
t_1>0且z_0+v_zt_1\in[0,h]
t1>0且z0+vzt1∈[0,h]
满足则输出
t
1
t_1
t1,不满足则为
t
2
t_2
t2
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <cmath>
using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define MIN(x,y) x < y ? x : y
#define MAX(x,y) x > y ? x : y
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
const double eps = 1e-09;
const double PI = acos(-1.0);
int main(){
int t,ca=1;cin>>t;
while(t--){
double r,h,x0,y0,z0,vx,vy,vz;
scanf("%lf%lf",&r,&h);
scanf("%lf%lf%lf",&x0,&y0,&z0);
scanf("%lf%lf%lf",&vx,&vy,&vz);
double a=vx*vx*h*h+vy*vy*h*h-vz*vz*r*r;
double b=2*x0*vx*h*h+2*y0*vy*h*h+2*h*vz*r*r-2*z0*vz*r*r;
double c=x0*x0*h*h+y0*y0*h*h-r*r*h*h+2*h*z0*r*r-z0*z0*r*r;
double x1=(-b+sqrt(b*b-4*a*c))/(2*a);
double x2=(-b-sqrt(b*b-4*a*c))/(2*a);
// printf("%lf %lf %lf\n",a,b,c);
// printf("%lf %lf\n",x1,x2);
if(x1>x2) swap(x1,x2);
printf("Case %d: ",ca++);
if(x1 < 0) printf("%.10lf\n",x2);
else{
double z1=z0+vz*x1;
if(z1<0 || z1>h) printf("%.10lf\n",x2);
else printf("%.10lf\n",x1);
}
}
return 0;
}
/*
*/