Live2d Test Env

HDU - 6167: Missile Interception (二分+圆的交)

pro:二维平面上,给点N个导弹的初始位置,射出方向,速度。问你是找一点,可以从这一点向任意方向发出拦截导弹,速度未V,最小化最大拦截导弹的时间。  如果要拦截一个导弹,必须在导弹发射之后才可以发射拦截导弹。 题意满足V>max(v导弹)。

sol:由于V>vmax,所以有二分的性质,那么这道题其实是个水题,(开始没注意到这个条件,一直不知道怎么去做);    

      N个导弹,我们把导弹的目的地内V*time的圆画出来,拦截导弹的发射位置在这个圆内,如果N个圆有交点,说明合法。 由于V>xmax,所以time越大,圆越大,且同一个导弹对应的圆有包含关系,所以满足二分性质。

       现在的问题救是 :我们去找可能的关键点,使之被N个圆包含。 这样的关键点是圆与圆的交点,以及被包含的圆内一点(圆心也行,我的代码写的圆心)。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
const double eps=1e-8;
const double pi=acos(-1.0);
struct point{
    double x,y;
    point(){}
    point(double xx,double yy):x(xx),y(yy){}
};
double dot(point a,point b){ return a.x*b.x+a.y*b.y;}
double det(point a,point b){ return a.x*b.y-a.y*b.x;}
point operator +(point a,point b){ return point(a.x+b.x,a.y+b.y);}
point operator -(point a,point b){ return point(a.x-b.x,a.y-b.y);}
point operator *(point a,double x){ return point(a.x*x,a.y*x);}
double dist(point a,point b){ return sqrt(dot(a-b,a-b));}
struct Circle{
    point p; double r;
}C[maxn];
point a[maxn],v[maxn],inter[maxn]; int N,tot; double V;
void CirinterCir(Circle a,Circle b)
{
    double dis=dist(a.p,b.p);
    if(dis>a.r+b.r+eps) return ;
    if(a.r-dis>=b.r-eps) { inter[++tot]=b.p; return ;}
    if(b.r-dis>=a.r-eps) { inter[++tot]=a.p; return ;}
    double angle1=atan2(b.p.y-a.p.y,b.p.x-a.p.x);
    double angle2=acos( (dis*dis+a.r*a.r-b.r*b.r)/(2.0*dis*a.r));
    inter[++tot]=point(a.p.x+a.r*cos(angle1+angle2),a.p.y+a.r*sin(angle1+angle2));
    inter[++tot]=point(a.p.x+a.r*cos(angle1-angle2),a.p.y+a.r*sin(angle1-angle2));
    return ;
}
bool ok(point a)
{
    rep(i,1,N){
        double dis=dist(a,C[i].p);
        if(dis>C[i].r+eps) return false;
    }
    return true;
}
bool check(double Mid)
{
    rep(i,1,N) C[i].r=Mid*V,C[i].p=a[i]+v[i]*Mid;
    tot=0;
    rep(i,1,N) rep(j,i+1,N) CirinterCir(C[i],C[j]);//cout<<tot<<endl;
    rep(i,1,tot) if(ok(inter[i])) return true;
    return false;
}
int main()
{
    while(~scanf("%d%lf",&N,&V)){
        rep(i,1,N){
           double x,L;
           scanf("%lf%lf%lf%lf%lf",&a[i].x,&a[i].y,&v[i].x,&v[i].y,&x);
           L=sqrt(dot(v[i],v[i]));
           v[i]=v[i]*(x/L);
        }
        int T=40; double L=0,R=10000,Mid,ans=0;
        while(T--){
            Mid=(L+R)/2;
            if(check(Mid)) ans=Mid,R=Mid;
            else L=Mid;
        }
        printf("%.4lf\n",ans);
    }
    return 0;
}

 

posted @ 2019-04-19 16:34  nimphy  阅读(260)  评论(0编辑  收藏  举报