算法学社
記錄難忘的征途
posts - 141,comments - 220,trackbacks - 0

题目描述:

   有个星球起始位置是(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 
posted on 2012-06-23 19:26 西月弦 阅读(466) 评论(0)  编辑 收藏 引用 所属分类: 解题报告

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理