• 【计算几何】【二分】【随机增量法】hdu6167 Missile Interception


    n个半径为R的圆是否有公共部分,等价于询问是否存在一个半径小于R的圆,能覆盖所有n个圆的圆心。

    对这n个点求最小圆覆盖即可。从网上扒了个随机增量法的代码。

    这样算上二分,复杂度就是nlogn了。

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const double eps=0.000000001;
    int n;
    double V,x[103],y[103],dx[103],dy[103],v[103],cx[103],cy[103];
    struct node  
    {  
        double x,y;  
    };   
    node p[1000001];  
    double r;  
    node O;  
      
    double dist(node a,node b)  
    {
        return sqrt( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) );  
    }
    void calc(double a,double b,double c,double d,double e,double f)
    {
        O.y=(c*d-f*a)/(b*d-e*a);  
        O.x=(c*e-f*b)/(a*e-b*d);  
    }
    double get()
    {
        for (int i=1;i<=n;++i)   
        {  
            p[i].x=cx[i];
            p[i].y=cy[i];
        }  
         O=p[1];r=0;                
           
         for(int i=2;i<=n;++i)        
         if(dist(O,p[i])>r+1e-6)   
         {  
             O=p[i];r=0;  
             for (int j=1;j<=i-1;++j)      
             if (dist(O,p[j])>r+1e-6)   
             {  
                 O.x=(p[i].x+p[j].x)/2;  
                 O.y=(p[i].y+p[j].y)/2;  
                 r=dist(O,p[j]);  
                 for (int k=1;k<=j-1;++k)     
                 if (dist(O,p[k])>r+1e-6)  
                 {  
                    calc(p[j].x-p[i].x,p[j].y-p[i].y,(p[j].x*p[j].x+p[j].y*p[j].y-p[i].x*p[i].x-p[i].y*p[i].y)/2,  
                         p[k].x-p[i].x,p[k].y-p[i].y,(p[k].x*p[k].x+p[k].y*p[k].y-p[i].x*p[i].x-p[i].y*p[i].y)/2);   
                   r=dist(O,p[k]);  
                 }   
             }  
         }  
         return r;
    }
    bool check(double t)
    {
        for(int i=1;i<=n;++i)
        {
            cx[i]=x[i]+dx[i]*t*v[i];
            cy[i]=y[i]+dy[i]*t*v[i];
        }
        return get()<t*V+eps;
    }
    int main()
    {
        while(scanf("%d%lf",&n,&V)!=EOF)
        {
            for(int i=1;i<=n;++i)
            {
                scanf("%lf%lf%lf%lf%lf",&x[i],&y[i],&dx[i],&dy[i],&v[i]);
                double l=sqrt(dx[i]*dx[i]+dy[i]*dy[i]);
                dx[i]/=l;
                dy[i]/=l;
            }
            double l=0,r=9999999;
            while(l<r-eps)
            {
                double mid=(l+r)*0.5;
                if(check(mid)) r=mid;
                else l=mid;
            }
            printf("%.4lf
    ",r);
        }
        return 0;
    }
  • 相关阅读:
    Android SharedPreferences 简单使用
    Android Broadcast广播
    Android Service 的生命周期
    Android RecyclerView的使用
    Android ListView addHeaderView()、addFooterView()和变更列表
    Android ListView的缓存机制
    Android ViewPager + Fragment的实现与Fragment生命周期管理
    Android 触摸事件的传递过程
    Java 泛型及相关使用
    android 常用View的一些注意点(CheckedTextView)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7414678.html
Copyright © 2020-2023  润新知