• 题解:

    • 只要确定了每艘飞船的就位位置,就可以用二分+网络流求得答案;
    • 定义偏转角度$a$为离$x$正半轴逆时针最近的边的弧度,$a \in [0,\frac{2\pi}{n})$
    • 二分一个值,对于一个点可以求出可到达的弧度记为$[l,r]$
    • 那么在$[0,a]$的移动范围内只有可能前面一个点删除,后面一个点加入;
    • 对$O(n)$个关键点做网络流即可;
    • 复杂度$O(n^4 \ logn)$
    • 如果将关键点排序,每次只考虑变化的边退流可以优化到:$O(n^3 \log n)$
    •  #include<bits/stdc++.h>
      #define ld double
      using namespace std;
      const int N=,M=,inf=0x3f3f3f3f;
      const ld Pi=acos(-),eps=1e-;
      int n,S,T,vis[N],hd[N],o,cur[N],d[N],que[N],head,tail,flow,cnt;
      ld R,B;
      struct Edge{int v,nt,f;}E[M<<];
      struct poi{ld x,y;}p[N];
      ld dis(poi A){return sqrt(A.x*A.x+A.y*A.y);}
      struct data{
      ld ang;int u,v,t;
      data(ld _ang=,int _u=,int _v=,int _t=):ang(_ang),u(_u),v(_v),t(_t){};
      bool operator <(const data&A)const{return ang==A.ang?t>A.t:ang<A.ang;}
      }q[N];
      bool bfs(){
      for(int i=S;i<=T;++i)vis[i]=,cur[i]=hd[i];
      head=tail=;vis[que[++tail]=S]=d[S]=;
      while(head<tail){
      int u=que[++head];
      for(int i=hd[u];~i;i=E[i].nt)if(E[i].f){
      int v=E[i].v;
      if(vis[v])continue;
      vis[v]=;d[v]=d[u]+;que[++tail]=v;
      if(v==T)return true;
      }
      }
      return false;
      }
      int dfs(int u,int c){
      if(u==T||!c)return c;
      int flow=,f;
      for(int i=cur[u];~i;i=E[i].nt){
      int v=E[cur[u]=i].v;
      if(d[v]==d[u]+&&(f=dfs(v,min(E[i].f,c)))){
      flow+=f;c-=f;
      E[i].f-=f;E[i^].f+=f;
      if(!c)break;
      }
      }
      return flow;
      }
      void add(int u,int v){
      E[o]=(Edge){v,hd[u],};hd[u]=o++;
      E[o]=(Edge){u,hd[v],};hd[v]=o++;
      }
      void del(int u,int v){
      int fg=;
      for(int i=hd[u];~i;i=E[i].nt)if(E[i].v==v){
      if(!E[i].f)flow--;else fg=;
      E[i].f=E[i^].f=;
      break;
      }
      if(fg)return;
      for(int i=hd[S];~i;i=E[i].nt)if(E[i].v==u){
      E[i].f=;E[i^].f=;break;
      }
      for(int i=hd[v];~i;i=E[i].nt)if(E[i].v==T){
      E[i].f=;E[i^].f=;break;
      }
      if(bfs())flow+=dfs(S,inf);
      }
      bool check(ld mid){
      flow=cnt=o=;
      for(int i=S;i<=T;++i)hd[i]=-;
      for(int i=;i<=n;++i){
      ld d=dis(p[i]);
      if(mid+d<=R||mid+R<=d)return false;
      if(R+d<=mid){
      for(int j=;j<=n;++j)add(i,j+n);
      continue;
      }
      ld ang=atan2(p[i].y,p[i].x);
      ld del=acos((d*d+R*R-mid*mid)/(*d*R));
      ld ang1=ang-del,ang2=ang+del;
      while(ang1<)ang1+=Pi*;
      while(ang2<)ang2+=Pi*;
      int l=ang1/B,r=ang2/B;
      ang1=ang1-B*l;
      ang2=ang2-B*r;
      l++;r++;
      q[++cnt]=(data){ang1,i,l,};
      q[++cnt]=(data){ang2,i,r,-};
      if(l<=r)for(int j=l+;j<=r;++j)add(i,j+n);
      else {
      for(int j=;j<=r;++j)add(i,j+n);
      for(int j=l+;j<=n;++j)add(i,j+n);
      }
      }
      sort(q+,q+cnt+);
      for(int i=;i<=n;++i)add(S,i),add(i+n,T);
      while(bfs())flow+=dfs(S,inf);
      if(flow==n)return true;
      for(int i=;i<=cnt;++i){
      if(~q[i].t){
      add(q[i].u,q[i].v+n);
      if(bfs())flow+=dfs(S,inf);
      if(flow==n)return true;
      }
      else del(q[i].u,q[i].v+n);
      }
      return false;
      }
      int main(){
      #ifndef ONLINE_JUDGE
      freopen("P4518.in","r",stdin);
      freopen("P4518.out","w",stdout);
      #endif
      scanf("%d%lf",&n,&R);
      B=*Pi/n;S=,T=n*+;
      for(int i=;i<=n;++i)scanf("%lf%lf",&p[i].x,&p[i].y);
      ld l=,r=;
      while(r-l>eps){
      ld mid=(l+r)/;
      if(check(mid))r=mid;
      else l=mid;
      }
      printf("%.8lf\n",l+eps);
      return ;
      }

LGP4518[JSOI2018]绝地反击的更多相关文章

  1. 【BZOJ5316】[JSOI2018]绝地反击(网络流,计算几何,二分)

    [BZOJ5316][JSOI2018]绝地反击(网络流,计算几何,二分) 题面 BZOJ 洛谷 题解 很明显需要二分一个答案. 那么每个点可以确定的范围就是以当前点为圆心,二分出来的答案为半径画一个 ...

  2. BZOJ5316 : [Jsoi2018]绝地反击

    若$R=0$,那么显然答案为离原点最远的点到原点的距离. 否则若所有点都在原点,那么显然答案为$R$. 否则考虑二分答案$mid$,检查$mid$是否可行. 那么每个点根据对应圆交,可以覆盖圆上的一部 ...

  3. 洛谷P4518 [JSOI2018]绝地反击(计算几何+二分图+退流)

    题面 传送门 题解 调了咱一个上午-- 首先考虑二分答案,那么每个点能够到达的范围是一个圆,这个圆与目标圆的交就是可行的区间,这个区间可以用极角来表示 首先,如果我们知道这个正\(n\)边形的转角,也 ...

  4. yyb省选前的一些计划

    突然意识到有一些题目的计划,才可以减少大量查水表或者找题目的时间. 所以我决定这样子处理. 按照这个链接慢慢做. 当然不可能只做省选题了. 需要适时候夹杂一些其他的题目. 比如\(agc/arc/cf ...

  5. LOJ 2548 「JSOI2018」绝地反击 ——二分图匹配+网络流手动退流

    题目:https://loj.ac/problem/2548 如果知道正多边形的顶点,就是二分答案.二分图匹配.于是写了个暴力枚举多边形顶点的,还很愚蠢地把第一个顶点枚举到 2*pi ,其实只要 \( ...

  6. 【LOJ】#2548. 「JSOI2018」绝地反击

    题解 卡常卡不动,我自闭了,特判交上去过了 事实上90pts= = 我们考虑二分长度,每个点能覆盖圆的是一段圆弧 然后问能不能匹配出一个正多边形来 考虑抖动多边形,多边形的一个端点一定和圆弧重合 如果 ...

  7. 【JSOI2018】绝地反击

    题面 50pts 首先当然是二分答案\(mid\), 对于每一个点,以它为圆心的圆,交上攻击轨道: 那么这个点到攻击轨迹的可达范围就是一段圆弧. 怎么求这段圆弧呢? 我们知道圆弧可以用其两端点对于圆心 ...

  8. JSOI2018简要题解

    来自FallDream的博客,未经允许,请勿转载,谢谢. 有幸拜读到贵省的题目,题的质量还不错,而且相比zjoi可做多了,简单发一下题解吧. 还有就是,怎么markdown在博客园上的代码这么丑啊 「 ...

  9. JSOI2018 简要题解

    潜入行动 复杂度分析题. 定义状态fi,j,0/1,0/1f_{i,j,0/1,0/1}fi,j,0/1,0/1​表示以iii为根子树放jjj个机器iii这个放不放,iii这个是否已放来进行dpdpd ...

随机推荐

  1. 使用NNI的scikit-learn以及Tensorflow分析

    一.NNI简介 NNI (Neural Network Intelligence) 是自动机器学习(AutoML)的工具包. 它通过多种调优的算法来搜索最好的神经网络结构和(或)超参,并支持单机.本地 ...

  2. zookeeper_节点数据版本号问题

    转自:Simba_cheng 更新节点数据的方法: 同步方法:Stat setData(final String path, byte data[], int version) 异步方法:void s ...

  3. win10浏览器访问vmware中ubuntu开启的某个服务端口出现的问题

    问题描述 1. win10系统中浏览器能正常访问  ubuntu中nginx服务器的80端口, 但是不能访问8082 问题原因 ubuntu 防火墙默认没有启用 8082端口, 需要开启这个端口号 解 ...

  4. Vue 入门之数据绑定

    什么是双向绑定? Vue 框架很核心的功能就是双向的数据绑定. 双向是指:HTML 标签数据 绑定到 Vue 对象,另外反方向数据也是绑定的.通俗点说就是,Vue 对象的改变会直接影响到 HTML 的 ...

  5. sprint2(第三天)

    展板 燃尽图

  6. MySQL课堂练习 20162315

    练习内容 1.参考教材相关代码,提交能连接到world的截图(有学号水印) 2.查询world数据库,获得人口超过500万的所有城市的列表. 3.查询world数据库,获得New Jersey州所有城 ...

  7. validating & update ctabfolder css

    总是查错 结果把validating全部都反选,然后老是update ctabfolder css update ctabfolder css has encountered a problem An ...

  8. 【贪心算法】POJ-3040 局部最优到全局最优

    一.题目 Description As a reward for record milk production, Farmer John has decided to start paying Bes ...

  9. 【CSAPP笔记】13. 链接

    下面就要进入本书的第二部分--在系统上运行程序.书的第一部分,主要是研究单个应用程序,关注的是数据类型.机器指令.程序性能.存储器系统等话题.在书的第二部分,我们继续对计算机系统的探索.现代操作系统与 ...

  10. ADT队列/FIFO表

    队列是一种特殊的表,只在表首进行删除,只在表尾进行插入,按照先进先出原则操作(First In First Out),又称为FIFO表: 队列的指针实现代码: #include<cstdio&g ...