Description
有 n n 个导弹,第个导弹从 (xi,yi) ( x i , y i ) 位置发射,沿 (dxi,dyi) ( d x i , d y i ) 方向,速度为 vi v i ,现在要建立一个导弹防御阵地来拦截这些导弹,从导弹防御阵地可以往任意方向发射速度为 V V 的导弹,要求适当选取导弹阵地的位置使得拦截这些导弹的最长用时最短,输出这个最小值
Input
多组用例,每组用例首先输入两个整数表示导弹的数量和导弹防御阵地的导弹速度,之后 n n 行每行输入五个整数表示第 i i 枚导弹的发射起点,发射方向和速度
Output
对于每组用例,输出拦截导弹最长时间的最小值吗,保留到小数点后四位
Sample Input
2 2
2 0 3 0 1
0 0 3 1 1
2 2
0 0 0 1 1
0 2 0 -1 1
Sample Output
0.5081
0.3333
Solution
二分答案 ans a n s (达到 10−4 10 − 4 的精度二分 60 60 次足够),这样就得到了这些导弹可以飞行的最远距离,以这些导弹可以到达的最远位置为圆心, ans⋅V a n s ⋅ V 为半径画一个圆,那么只要导弹防御基地在这个圆内就可以拦截该枚导弹,只要这 n n 个圆有公共部分则该答案合法,故问题转化为求个圆的公共部分,注意到必然有两个圆的交点在 n n 个圆的公共部分边界,故枚举两个圆求出交点,然后判断该交点到每个圆心的距离是否都不超过即可,时间复杂度 O(60n3) O ( 60 n 3 )
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define eps 1e-8
#define maxn 105
struct Point
{
double x,y;
Point(){}
Point(double _x,double _y)
{
x=_x;y=_y;
}
Point operator +(const Point &b)const
{
return Point(x+b.x,y+b.y);
}
Point operator -(const Point &b)const
{
return Point(x-b.x,y-b.y);
}
double operator ^(const Point &b)const
{
return x*b.y-y*b.x;
}
double operator *(const Point &b)const
{
return x*b.x+y*b.y;
}
Point operator *(const double &b)const
{
return Point(x*b,y*b);
}
}p[maxn],d[maxn],pp[maxn];
int sgn(double x)
{
if(fabs(x)<eps) return 0;
if(x<0) return -1;
return 1;
}
double dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int n;
double V,v[maxn];
void Intersection(Point a,Point b,double R,Point *q)
{
double D=dis(a,b);
double ang1=atan2(b.y-a.y,b.x-a.x);
double ang2=acos(0.5*D/R);
q[0]=Point(a.x+R*cos(ang1+ang2),a.y+R*sin(ang1+ang2));
q[1]=Point(a.x+R*cos(ang1-ang2),a.y+R*sin(ang1-ang2));
}
bool check(double mid)
{
double R=mid*V;
for(int i=1;i<=n;i++)pp[i]=p[i]+d[i]*(mid*v[i]/dis(Point(0,0),d[i]));
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
double D=dis(pp[i],pp[j]);
if(sgn(D)==0&&n==2)return 1;
if(sgn(D)>0&&sgn(D-2.0*R)<=0)//相交
{
Point q[2];
Intersection(pp[i],pp[j],R,q);
for(int l=0;l<2;l++)
{
int flag=1;
for(int k=1;k<=n;k++)
if(sgn(dis(q[l],pp[k])-R)>0)
{
flag=0;
break;
}
if(flag)return 1;
}
}
}
return 0;
}
int main()
{
while(~scanf("%d%lf",&n,&V))
{
for(int i=1;i<=n;i++)scanf("%lf%lf%lf%lf%lf",&p[i].x,&p[i].y,&d[i].x,&d[i].y,&v[i]);
double l=0,r=1000,mid;
int t=60;
while(t--)
{
mid=0.5*(l+r);
if(check(mid))r=mid;
else l=mid;
}
printf("%.4f\n",mid);
}
return 0;
}