• LGP4518[JSOI2018]绝地反击


    • 题解:

      • 只要确定了每艘飞船的就位位置,就可以用二分+网络流求得答案;
      • 定义偏转角度$a$为离$x$正半轴逆时针最近的边的弧度,$a in [0,frac{2pi}{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
        ",l+eps);
        119     return 0;
        120 }
        View Code
  • 相关阅读:
    sql 四大排名函数--简介
    Markdown语法规则
    利用ADO操作外部数据——Excel之VBA(15)
    VBA中的用户信息交换——Excel之VBA(14)
    窗体和控件(2)——Excel之VBA(13)
    窗体和控件(1)——Excel之VBA(12)
    使用VBA数组公式——Excel之VBA(11)
    使用DIR函数合并多个文件的数据——Excel之VBA(10)
    ubuntu jupter python虚拟环境
    Pytorch_加载自己的数据集并训练
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10410257.html
Copyright © 2020-2023  润新知