转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目:行星围绕着恒星转,飞船用最少的时间抵达行星上,不能距离恒星太近,问最少时间。
二分答案,然后可以算出行星的末位置,计算出飞船到目标位置的最短距离,判断一下最短距离是否小于飞船的速度乘以时间。
其中最短距离分为两种情况,可以是直线,可能是两条切线+一段弧。
其中那段弧的圆心角是先计算出两点之间的夹角,然后减去两个直角三角形的内角。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<string>
#include<vector>
#define eps 1e-10
#define LL long long
#define LD long double
#define pi acos(-1.0)
using namespace std;
struct Point{
LD x,y;
}per,qwe,goal,central;
LD v,vp,r,R,ang;
LD Dist(Point p1,Point p2){
return (LD)sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
LD slove(LD t){
LD angle=(ang+t*vp/R); //目标位置的角度
goal.x=R*cos(angle),goal.y=R*sin(angle); //目标位置坐标
//cout<<goal.x<<" "<<goal.y<<endl;
LD qiexian1=sqrt(qwe.x*qwe.x+qwe.y*qwe.y-r*r); //起始位置与恒星安全区的切线长度
LD qiexian2=sqrt(goal.x*goal.x+goal.y*goal.y-r*r); //目标位置与恒星安全区的切线长度
LD dist=Dist(qwe,goal); //起始位置与目标位置之间的距离
if(dist<qiexian2+qiexian1) { //从起始位置到目标位置的直线与安全区不相交
// cout<<dist<<endl;
return dist;
}
else{
LD dist1=Dist(qwe,central);
LD dist2=Dist(goal,central);
LD centralangle=acos((dist1*dist1+dist2*dist2-dist*dist)/(2*dist1*dist2))-atan(qiexian1/r)-atan(qiexian2/r); //扇形的圆心角
// cout<<centralangle*r+qiexian1+qiexian2<<endl;
return centralangle*r+qiexian1+qiexian2;
}
}
int main(){
central.x=central.y=0;
while(scanf("%lf%lf%lf%lf%lf%lf%lf",&per.x,&per.y,&vp,&qwe.x,&qwe.y,&v,&r)!=EOF){
ang=atan2(per.y,per.x); //行星初始角度
R=sqrt(per.x*per.x+per.y*per.y); //行星轨迹半径
LD high=1000000,low=0,mid;
while(high-low>eps){
mid=(low+high)/2;
if(slove(mid)<=eps+mid*v)
high=mid;
else
low=mid;
}
printf("%.10f\n",mid);
}
return 0;
}
/*
10 0 1
-10 0 2 8
50 60 10
50 60 20 40
*/