问题描述
进取号再次受命出击!
由于Spock去了平行世界,Kirk船长决定让你来计算一下到达目的地需要多长时间。
由于原来的问题比较复杂,我们进行一些简化。你的目的地是一颗正在围绕着一颗恒星转动的行星。恒星、行星和飞船都可以视为一个二位平面中的点。飞船现在的坐标是(x,y),飞行的速度是v。行星绕着在(0,0)点的恒星做半径为R,速度为vp的逆时针的圆周运动。行星绕着恒星转动一周的时间就是2πR/vp。由于恒星自身行星现在的坐标是(xp, yp)。由于恒星非常热,所以飞船不能飞到距离恒星小于r的范围内。
作为一项十万火急的任务,飞船需要用尽量短的时间到达目的地。现在,请你写一个程序来完成Kirk船长交给你的任务吧!
输入第一行为三个整数:xp, yp and vp,分别表示行星的坐标和速度- 104 ≤ xp, yp ≤ 104, 1 ≤ vp < 104。第二行包含四个整数:x,y,v,r,非别表示现在飞船的位置、飞船的速度和恒星的安全距离。
数据保证r2 < x2 + y2, r2 < xp2 + yp2 and vp < v
输出包含一个浮点数,表示最短需要的时间,结果四舍五入到小数点后6位。
|
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
|
以文本方式显示
|
1秒 | 64M | 0 |
大致思路:
利用二分的方法进行求解,对时间进行二分,最后找到符合精度的相应时间。
具体实现:
张哲华大神的帖子已经说的很详细了,我也是参考这个帖子写的。但是我要稍稍的补充一下,就是关于最后相遇位置坐标的求法,一开始的时候我用了比较麻烦的求解相应坐标的方法,但是只有第一个用例过了,后来改成这样就对了。
du=(v1*mid)/R;yt=sin(du)*x1+cos(du)*y1;xt=cos(du)*x1-sin(du)*y1;(mid表示时间,du表示走过的度数,x1,y1为行星开始时的坐标)
注意事项:
(1)程序中会大量的运用到三角函数,而三角函数的参数都是双精度型的,所以如果在输入的时候采用整形输入的话使用相应函数的时候要注意参数,如果参数是整形的需要将其转化为双精度型的。
(2)弧长的计算公式为,r*角度。
(3)注意最后二分的结束条件,要符合相应的精度。
实现代码
<span style="font-family:Microsoft YaHei;font-size:14px;">#include<stdio.h> #include<math.h> #define pai 3.1415926 int main() { int x1,x,y1,y; int r,v1,v,zhengshu; double xt,yt,bei,dushu,du; double d,R,t1,dse,c,D; double left,right,mid; double s1,s2,s3,s4; scanf("%d %d %d",&x1,&y1,&v1); scanf("%d %d %d %d",&x,&y,&v,&r); R=sqrt((double)(x1*x1+y1*y1)); //行星飞行半径 c=2*pai*R; t1=c/v1; s1=sqrt((double)(x*x+y*y-r*r)); s3=sqrt((double)(x*x+y*y)); left=0.0; right=10000000000.0; while(right-left>0.000000001) { mid=(right+left)/2; D=v*mid; //bei=v1*mid/c; //zhengshu=floor(bei); // dushu=(bei-zhengshu)*360-acos(x1/R); //du=dushu*pai/180; //xt=R*cos(du); //yt=R*sin(du); dushu=(v1*mid)/R; yt=sin(dushu)*x1+cos(dushu)*y1; xt=cos(dushu)*x1-sin(dushu)*y1; dse=sqrt((double)((x-xt)*(x-xt)+(y-yt)*(y-yt))); s2=sqrt((double)(xt*xt+yt*yt-r*r)); s4=sqrt((double)(xt*xt+yt*yt)); if(dse<s1+s2) { d=dse; } else { d=s1+s2+(acos((s3*s3+s4*s4-dse*dse)/(2*s3*s4))-atan(s1/r)-atan(s2/r))*r; } if(d>D) { left=mid; } else { right=mid; } } printf("%.6lf\n",mid); return 0; }</span>