codeforces 198C 二分答案 + 计算几何

codeforces 198C 二分答案 + 计算几何

题目描述:

   有个星球起始位置是(xp,yp),绕原点以速度Vp做匀速圆周运动。不明物体起始位置(x,y),速度为V(V>Vp)。这个物体可以随意移动,但是任何时刻与原点的距离不能小于r。请问这个物体想要与星球位置重合的最少时间是多少?

吐槽:

    1. 这么猥琐的计算几何居然被我捉掉了真是让我不得不单独拿出一篇随笔来写阿。。。。。。。。
    2. 其实是参照bmerry大神的代码的。。。。。。。。。。

算法分析:

    二分时间(至于为何可以二分就不讲了),先用二维仿射几何计算出星球的新位置P。
    再计算不明物体是否可以在这个时间内运动到那个新位置处。
    
    如果二者连线形成的线段到原点距离不小于r。那么直接做直线运动。
    如果小于r, 判断是否和r的内圆相交。
    如果相交的话,求出四条切线。 切线的线段长是固定的,要在小圆上选择一个最优的弧。
    因为切点只有四个,直接枚举即可。
 1 #include<iostream>
 2 #include<complex>
 3 #include<cmath>
 4  using  namespace std;
 5  #define eps 1e-9
 6 typedef complex < double> pnt;
 7  const  double PI = acos(-1);
 8  static  double dot ( const pnt& a,  const pnt& b) {  return real(conj(a) * b);}
 9  static  double cross( const pnt&a,  const pnt& b) {  return imag(conj(a) * b);}
10 inline  void chkmin( double &a, const  double b){  if(a>b) a = b;}
11  double dist(pnt a, pnt b, double r){
12      double ab = abs(a-b);
13      if(ab < eps)  return ab;
14      if(abs(cross(a ,a-b) / ab) >= r)  return ab;
15      if(dot ( -a, b-a) < 0.0 || dot(-b, a-b) <0.0)  return ab;
16  //     cout<<a<<" "<<dot(a,a)<<" "<<r*r<<endl;
17       double  as = sqrt(dot(a,a) - r*r);
18      double bs = sqrt(dot(b,b) - r*r);
19      double a_ang = arg(pnt(r, as));
20      double b_ang = arg(pnt(r,bs));
21      double A[2] = {arg(a) + a_ang, arg(a) - a_ang};
22      double B[2] = {arg(b) + b_ang, arg(b) - b_ang};
23      double ans = PI*2;
24      for( int i=0;i<2;i++)
25          for( int j=0;j<2;j++){
26              double ang = abs(A[i] - B[j]);
27              while(ang > PI*2) ang -= PI*2;
28              if(ang > PI) ang = 2*PI - ang;
29             chkmin(ans , ang);
30         }
31  //     cout<<as<<" "<<bs<<" "<<r*ans<<endl;
32       return  as + bs + r * ans;
33 }
34  int main(){
35      double xp,yp,vp,x,y,v,rp;
36      while(cin >> xp >> yp >> vp >> x >> y >> v >> rp){
37         pnt p1 = pnt(xp,yp);
38         pnt p0 = pnt(x,y);
39          double l = 0, r = 1e9;
40          double R = abs(p1);
41          while(abs(r-l) > eps){
42              double t = (l+r) * 0.5;
43             pnt P = p1 * exp(pnt(0,t*vp / R));
44              double d = dist(p0,P,rp);
45  //             cout<<P<<endl;
46  //             cout<<l<<" "<<r<<" "<<t<<" "<<d<<endl;
47               if(d <= v*t) r = t;
48              else l = t;
49         }
50         cout.precision(9);
51         cout << l << endl;
52     }
53 }
54 

你可能感兴趣的:(codeforces 198C 二分答案 + 计算几何)