转自:http://www.cnblogs.com/kuangbin/archive/2012/08/23/2653003.html
一种是直接根据公式计算的,另外一种是二分算出来的。两种方法速度都很快,充分体会到二分的效率之高啊~~~
题目中一个很重要的条件就是 (Lx*Lx+Ly*Ly) < vD*vD < vB*vB ,
这样说明一定是可以追上的,而且可以以最大的距离射中,所以第一问的答案一定就是L的。
假设追击者跑的时间是 t1,那么肯定子弹飞行时间就是 L/vB 了
那么此时被追击者的位置就是 A(x1+(t1+L/vB)*Lx,y1+(t1+L/vB)*Ly )了
那么 点 (x2,y2) 到点A的距离等于 L+vD*t1 或者是 L-vD*t1 //两个方程
联立一个一元二次方程,很容易解出来。上面有两个方程,可以求得4个解。
那么选择其中最小的非负解就是答案了。
注意最后时间要加上 L/vB
1 /* 2 HDU 4024 3 找数学公式计算 4 */ 5 6 #include<stdio.h> 7 #include<iostream> 8 #include<math.h> 9 #include<string.h> 10 using namespace std; 11 12 int main() 13 { 14 //freopen("D.in","r",stdin); 15 //freopen("D.out","w",stdout); 16 double x1,y1,x2,y2,Lx,Ly,vD,vB,L; 17 while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&Lx,&Ly,&vD,&vB,&L)) 18 { 19 if(x1==0&&y1==0&&x2==0&&y2==0&&Lx==0&&Ly==0&&vD==0&&vB==0&&L==0)break; 20 double a=vD*vD-Lx*Lx-Ly*Ly; 21 double b=2*L*vD-2*Lx*(x1-x2+L*Lx/vB)-2*Ly*(y1-y2+L*Ly/vB); 22 double c=L*L-(x1-x2+L*Lx/vB)*(x1-x2+L*Lx/vB)-(y1-y2+L*Ly/vB)*(y1-y2+L*Ly/vB); 23 24 double s1=(-b-sqrt(b*b-4*a*c))/(2*a); 25 double s2=(-b+sqrt(b*b-4*a*c))/(2*a); 26 27 b=-2*L*vD-2*Lx*(x1-x2+L*Lx/vB)-2*Ly*(y1-y2+L*Ly/vB); 28 double s3=(-b-sqrt(b*b-4*a*c))/(2*a); 29 double s4=(-b+sqrt(b*b-4*a*c))/(2*a); 30 31 printf("%.3lf ",L); 32 //从s1 s2 s3 s4当中选出一个最小的正数 33 if(s1<0)s1=10000000000.0; 34 if(s2<0)s2=10000000000.0; 35 if(s3<0)s3=10000000000.0; 36 if(s4<0)s4=10000000000.0; 37 printf("%.3lf ",min(s1,min(s2,min(s3,s4)))+L/vB);//不要忘记加上L/vB 38 } 39 return 0; 40 }
1 /* 2 HDU 4024 3 二分 4 */ 5 #include<stdio.h> 6 #include<iostream> 7 #include<math.h> 8 #include<algorithm> 9 using namespace std; 10 const double eps=1e-8;//1e-6会WR 11 const double INF=1e9; 12 int main() 13 { 14 //freopen("D.in","r",stdin); 15 //freopen("D.out","w",stdout); 16 double x1,y1,x2,y2,Lx,Ly,vD,vB,L; 17 while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&Lx,&Ly,&vD,&vB,&L)) 18 { 19 if(x1==0&&y1==0&&x2==0&&y2==0&&Lx==0&&Ly==0&&vD==0&&vB==0&&L==0)break; 20 double l=0; 21 double r=INF; 22 double mid; 23 double x,y; 24 while(l<r-eps) 25 { 26 mid=(l+r)/2; 27 x=x1+mid*Lx; 28 y=y1+mid*Ly; 29 double d=sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2));//两点距离 30 double d1=vD*(mid-L/vB);//勇士跑的最大距离 31 if(d<=L)//在圆里面 平行关系 32 { 33 if(d+d1<=L)l=mid;//到不了圆周上 34 else r=mid; 35 } 36 else 37 { 38 if(L+d1<=d)l=mid;//到不了圆周上 39 else r=mid; 40 } 41 } 42 printf("%.3lf %.3lf ",L,mid); 43 } 44 return 0; 45 }