LGP4518[JSOI2018]绝地反击

 

  • 题解:

    • 只要确定了每艘飞船的就位位置,就可以用二分+网络流求得答案;
    • 定义偏转角度$a$为离$x$正半轴逆时针最近的边的弧度,$a \in [0,\frac{2\pi}{n})$
    • 二分一个值,对于一个点可以求出可到达的弧度记为$[l,r]$
    • 那么在$[0,a]$的移动范围内只有可能前面一个点删除,后面一个点加入;
    • 对$O(n)$个关键点做网络流即可;
    • 复杂度$O(n^4 \ logn)$
    • 如果将关键点排序,每次只考虑变化的边退流可以优化到:$O(n^3 \log n)$
    •   1 #include<bits/stdc++.h>
        2 #define ld double
        3 using namespace std;
        4 const int N=610,M=100010,inf=0x3f3f3f3f;
        5 const ld Pi=acos(-1),eps=1e-9;
        6 int n,S,T,vis[N],hd[N],o,cur[N],d[N],que[N],head,tail,flow,cnt;
        7 ld R,B;
        8 struct Edge{int v,nt,f;}E[M<<1];
        9 struct poi{ld x,y;}p[N];
       10 ld dis(poi A){return sqrt(A.x*A.x+A.y*A.y);}
       11 struct data{
       12     ld ang;int u,v,t;
       13     data(ld _ang=0,int _u=0,int _v=0,int _t=0):ang(_ang),u(_u),v(_v),t(_t){};
       14     bool operator <(const data&A)const{return ang==A.ang?t>A.t:ang<A.ang;}
       15 }q[N];
       16 bool bfs(){
       17     for(int i=S;i<=T;++i)vis[i]=0,cur[i]=hd[i];
       18     head=tail=0;vis[que[++tail]=S]=d[S]=1;  
       19     while(head<tail){
       20         int u=que[++head];
       21         for(int i=hd[u];~i;i=E[i].nt)if(E[i].f){
       22             int v=E[i].v;
       23             if(vis[v])continue;
       24             vis[v]=1;d[v]=d[u]+1;que[++tail]=v; 
       25             if(v==T)return true;
       26         }
       27     }
       28     return false;
       29 }
       30 int dfs(int u,int c){
       31     if(u==T||!c)return c;
       32     int flow=0,f;
       33     for(int i=cur[u];~i;i=E[i].nt){
       34         int v=E[cur[u]=i].v;
       35         if(d[v]==d[u]+1&&(f=dfs(v,min(E[i].f,c)))){
       36             flow+=f;c-=f;
       37             E[i].f-=f;E[i^1].f+=f;
       38             if(!c)break;
       39         }
       40     }
       41     return flow;
       42 }
       43 void add(int u,int v){
       44     E[o]=(Edge){v,hd[u],1};hd[u]=o++;
       45     E[o]=(Edge){u,hd[v],0};hd[v]=o++;
       46 }
       47 void del(int u,int v){
       48     int fg=0;
       49     for(int i=hd[u];~i;i=E[i].nt)if(E[i].v==v){
       50         if(!E[i].f)flow--;else fg=1;
       51         E[i].f=E[i^1].f=0;
       52         break;
       53     }
       54     if(fg)return;
       55     for(int i=hd[S];~i;i=E[i].nt)if(E[i].v==u){
       56         E[i].f=1;E[i^1].f=0;break;
       57     }
       58     for(int i=hd[v];~i;i=E[i].nt)if(E[i].v==T){
       59         E[i].f=1;E[i^1].f=0;break;
       60     }
       61     if(bfs())flow+=dfs(S,inf); 
       62 }
       63 bool check(ld mid){
       64     flow=cnt=o=0;
       65     for(int i=S;i<=T;++i)hd[i]=-1;
       66     for(int i=1;i<=n;++i){
       67         ld d=dis(p[i]);
       68         if(mid+d<=R||mid+R<=d)return false;
       69         if(R+d<=mid){
       70             for(int j=1;j<=n;++j)add(i,j+n);
       71             continue;
       72         }
       73         ld ang=atan2(p[i].y,p[i].x);
       74         ld del=acos((d*d+R*R-mid*mid)/(2*d*R));
       75         ld ang1=ang-del,ang2=ang+del;
       76         while(ang1<0)ang1+=Pi*2;
       77         while(ang2<0)ang2+=Pi*2;
       78         int l=ang1/B,r=ang2/B;
       79         ang1=ang1-B*l;
       80         ang2=ang2-B*r;
       81         l++;r++;
       82         q[++cnt]=(data){ang1,i,l,1};
       83         q[++cnt]=(data){ang2,i,r,-1};
       84         if(l<=r)for(int j=l+1;j<=r;++j)add(i,j+n);
       85         else {
       86             for(int j=1;j<=r;++j)add(i,j+n);
       87             for(int j=l+1;j<=n;++j)add(i,j+n);
       88         }
       89     }
       90     sort(q+1,q+cnt+1);
       91     for(int i=1;i<=n;++i)add(S,i),add(i+n,T);
       92     while(bfs())flow+=dfs(S,inf);
       93     if(flow==n)return true;
       94     for(int i=1;i<=cnt;++i){
       95         if(~q[i].t){
       96             add(q[i].u,q[i].v+n);
       97             if(bfs())flow+=dfs(S,inf);
       98             if(flow==n)return true;
       99         }
      100         else del(q[i].u,q[i].v+n);
      101     }
      102     return false;
      103 }
      104 int main(){
      105     #ifndef ONLINE_JUDGE
      106     freopen("P4518.in","r",stdin);
      107     freopen("P4518.out","w",stdout);
      108     #endif
      109     scanf("%d%lf",&n,&R);
      110     B=2*Pi/n;S=0,T=n*2+1;
      111     for(int i=1;i<=n;++i)scanf("%lf%lf",&p[i].x,&p[i].y);
      112     ld l=0,r=200;
      113     while(r-l>eps){
      114         ld mid=(l+r)/2;
      115         if(check(mid))r=mid;
      116         else l=mid;
      117     }
      118     printf("%.8lf\n",l+eps);
      119     return 0;
      120 }
      View Code

       

 

posted @ 2019-02-21 08:03  大米饼  阅读(370)  评论(0编辑  收藏  举报