吉林区域赛 E - The Tower 几何题
https://vjudge.net/contest/386991#problem/E
转自:https://blog.csdn.net/Du_Mingm/article/details/89791220
题意:给出一个底部圆圆心为(0,0,0),半径为r,高为h的圆锥,问起始位置为(x0,y0,z0),方向为(vx,vy,vz)的点撞上圆锥的时间。
有三角形相似,易知
然后带入对于所在平面带入圆的方程得
这就是圆锥面的方程了(底面是)
然后我们设所用时间为
易知撞击点为
然后把它带入圆锥面方程,得到关于的一元二次方程,求解即可
相撞点也可能是在底面上(易知z=0,由此解出),所以
撞击点也可能是,这个点不一定在内,所以要判断下
你以为这样结束了吗,并没有,还有两个小坑点
这时候最近的点并不是答案,所以也要判断一下(也就是交点的z范围在0到h之间)
1 #include <bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int maxn = 1e5+7; 5 int T,Case; 6 int main(){ 7 for(scanf("%d",&T);T--;){ 8 double h,r; 9 double x,y,z,vx,vy,vz; 10 scanf("%lf%lf",&r,&h); 11 scanf("%lf%lf%lf",&x,&y,&z); 12 scanf("%lf%lf%lf",&vx,&vy,&vz); 13 double a = (vx*vx*h*h+vy*vy*h*h-r*r*vz*vz), 14 b = 2*(x*vx*h*h+y*vy*h*h+vz*h*r*r-vz*z*r*r), 15 c = h*h*x*x+h*h*y*y+2*h*r*r*z-r*r*z*z-r*r*h*h; 16 double tans1 = (-b+sqrt(b*b-4*a*c))/(2*a); 17 double tans2 = (-b-sqrt(b*b-4*a*c))/(2*a); 18 double ans = 1e18; 19 if(tans1>0){ 20 double tz = z+tans1*vz; 21 if(tz>=0&&tz<=h) 22 ans = min(ans,tans1); 23 } 24 if(tans2>0){ 25 double tz = z+tans2*vz; 26 if(tz>=0&&tz<=h) 27 ans = min(ans,tans2); 28 } 29 //printf("%f \n%f\n",tans1,tans2); 30 if(fabs(vz)>1e-6){ 31 double t = -z/vz; 32 double tx = x+t*vx,ty = y+t*vy; 33 if(tx*tx+ty*ty<=r*r) 34 ans = min(ans,t); 35 } 36 printf("Case %d: %.10f\n",++Case,ans); 37 } 38 return 0; 39 }