hdu6559 The Tower

http://acm.hdu.edu.cn/showproblem.php?pid=6559

赛后一分钟过了,整场全员互演,队友改了我原来的代码我不知道,最后5分钟改问题的时候拿的不是原版代码改的。。

这题就列一个方程,首先z>=0,那么一定是在上面的面相交的,那么高度一定是0<=l<=h,那么交点的x,y坐标满足在半径为R=r/h*(h-l),所以有z0+vz*t=R,(x0+vxt)^2+(y0+vyt)^2=R^2,就是一个关于t的一元二次方程了

注意一元二次方程的特殊情况,如果a=0,说明点的速度向量与圆锥的母线平行,此时只有一个解,如果a=0且b=0,那么说明点原来的位置就在圆锥的母线上,那么此时这个方程就没了,直接用(z0-h)/(-vz)来算就好了,否则就会计算出两个解t1<=t2,如果t1<0,说明t1是与上方的圆锥母线的虚面相交了,所以此时取t1,注意t1,t2都大于0的时候还要判断一下,如果t1还是与虚面相交,就要取t2,t2时z坐标才会在[0,h]之间,否则如果是与圆锥的实面有两个交点,那么就取较小的那个。

#include<bits/stdc++.h>
using namespace std;

const double eps=1e-10;

inline double mysqrt(double x)
{
  return sqrt(max(0.0,x));
}

int main()
{
  double r,h,x0,y0,z0,vx,vy,vz,ans,a,b,c,delta,t1,t2;
  int t;
  scanf("%d",&t);
  for(int i=1;i<=t;i++)
    {
      scanf("%lf%lf",&r,&h);
      scanf("%lf%lf%lf",&x0,&y0,&z0);
      scanf("%lf%lf%lf",&vx,&vy,&vz);
      a=vx*vx+vy*vy-(r*r*vz*vz/h/h);
      b=2*x0*vx+2*y0*vy-2*(r*r*z0*vz/h/h)+2*(r*r*vz/h);
      c=x0*x0+y0*y0-(r*r*z0*z0/h/h)+2*(r*r*z0/h)-r*r;
      if(a<-eps || a>eps)
	{
	  delta=mysqrt(b*b-4*a*c);
	  t1=(-b-delta)/(2*a);
	  t2=(-b+delta)/(2*a);
	  if(t1>t2) swap(t1,t2);
	  if(t1<eps)
	    ans=t2;
	  else
	  {
	  	if(z0+vz*t1>h)
	  		ans=t2;
	  	else
	  		ans=t1;
	  }
	}
      else if(b>eps || b<-eps)
	ans=-c/b;
      else
	ans=(z0-h)/(-vz);
      printf("Case %d: %.10f\n",i,ans);
    }
  return 0;
}

	

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/108429368
今日推荐