若$R=0$,那么显然答案为离原点最远的点到原点的距离。

否则若所有点都在原点,那么显然答案为$R$。

否则考虑二分答案$mid$,检查$mid$是否可行。

那么每个点根据对应圆交,可以覆盖圆上的一部分,每个可行方案都可以通过平移使得刚好卡住某个交点。

枚举每个交点,算出圆上$n$个位置的坐标,然后匈牙利算法判断是否存在完美匹配,时间复杂度$O(n^4\log w)$,不能承受。

注意到这个图是个稠密图,所以可以用bitset对匈牙利进行加速,做到$O(\frac{n^3}{32})$每次匹配。

另一方面,可以先枚举一个点$x$,然后再二分答案$mid$,判断是否有可行方案使得$x$刚好匹配$x$和圆的交点。

在这里,显然只需要在之前答案$ans$的基础之上往下二分,如果$ans-eps$不可行那么就没有继续二分的必要。

即:设$f[x]$表示$x$得到的最优解,若$f[x]$不是$f[1,x]$的最小值,那么就没有继续二分的必要。

考虑将读入的$n$个点随机打乱,那么$f[x]$是$f[1,x]$的最小值的概率为$\frac{1}{x}$,一共只有期望$O(\log n)$个$x$有二分的必要。

检查次数骤降为$O(n+\log n\log w)$,时间复杂度$O(\frac{(n+\log n\log w)n^3}{32})$。

注意要特判$mid$过小或者过大导致$x$与圆没有交点的情况。

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef unsigned int U;
const int N=205,M=7;
const double eps=1e-9,pi=acos(-1.0);
int n,m,R,i,j;double lim,ans,rot[N][2],b[N][2];
int f[N];U v[M],g[N][M];
struct P{int x,y;}a[N];
inline int sgn(double x){
if(x>eps)return 1;
if(x<-eps)return -1;
return 0;
}
bool find(int x){
for(int i=0;i<=m;i++){
U t=v[i]&g[x][i];
while(t){
int j=i<<5|__builtin_ctz(t);
v[i]^=1U<<(j&31);
if(f[j]<0||find(f[j]))return f[j]=x,1;
t-=t&-t;
}
}
return 0;
}
inline bool check(int A,int B,double C){
double d=sqrt(a[A].x*a[A].x+a[A].y*a[A].y);
double l=(a[A].x*a[A].x+a[A].y*a[A].y+C*C-R*R)/(2*d);
double h=sqrt(max(C*C-l*l,0.0));
double bx=-a[A].x/d,by=-a[A].y/d;
double px=a[A].x+bx*l,py=a[A].y+by*l;
by=-by;
swap(bx,by);
bx*=h,by*=h;
if(B==0)px+=bx,py+=by;else px-=bx,py-=by;
int i,j;
b[0][0]=px,b[0][1]=py;
for(i=1;i<n;i++){
b[i][0]=px*rot[i][1]-py*rot[i][0];
b[i][1]=px*rot[i][0]+py*rot[i][1];
}
C*=C;
for(i=0;i<n;i++){
for(j=0;j<=m;j++)g[i][j]=0;
for(j=0;j<n;j++)if(sgn((a[i].x-b[j][0])*(a[i].x-b[j][0])+(a[i].y-b[j][1])*(a[i].y-b[j][1])-C)<=0)g[i][j>>5]|=1U<<(j&31);
}
for(i=0;i<n;i++)f[i]=-1;
for(i=0;i<n;i++){
for(j=0;j<=m;j++)v[j]=~0U;
if(!find(i))return 0;
}
return 1;
}
int main(){
scanf("%d%d",&n,&R);
m=(n-1)>>5;
for(i=0;i<n;i++)scanf("%d%d",&a[i].x,&a[i].y);
if(!R){
int ans=0;
for(i=0;i<n;i++)ans=max(ans,a[i].x*a[i].x+a[i].y*a[i].y);
double ret=sqrt(ans);
return printf("%.15f",ret),0;
}
random_shuffle(a,a+n);
for(i=1;i<n;i++){
double o=pi*2*i/n;
rot[i][0]=sin(o),rot[i][1]=cos(o);
}
for(i=0;i<n;i++){
int t=a[i].x*a[i].x+a[i].y*a[i].y;
double val;
if(t<=R)val=R-sqrt(t);else val=sqrt(t)-R;
lim=max(lim,val);
ans=max(ans,sqrt(t)+R);
}
for(i=0;i<n;i++)if(a[i].x||a[i].y)for(j=0;j<2;j++){
double l=lim,r=max(min(sqrt(a[i].x*a[i].x+a[i].y*a[i].y)+R,ans-eps),lim);
if(!check(i,j,r))continue;
while(l+eps<r){
double mid=(l+r)/2;
if(check(i,j,mid))r=ans=mid;else l=mid;
}
}
return printf("%.15f",ans),0;
}

  

BZOJ5316 : [Jsoi2018]绝地反击的更多相关文章

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

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

  2. LGP4518[JSOI2018]绝地反击

    题解: 只要确定了每艘飞船的就位位置,就可以用二分+网络流求得答案: 定义偏转角度$a$为离$x$正半轴逆时针最近的边的弧度,$a \in [0,\frac{2\pi}{n})$ 二分一个值,对于一个 ...

  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. 2、jQuery的Ajax简单示例

    一.创建一个JavaWEBProject 二.创建一个Servlet(下面的例子中用到了Json--第32行,Json的作用是将一个Object类转换为特定格式的字符串,如果不用Json直接返回字符串 ...

  2. Coursera, Big Data 4, Machine Learning With Big Data (week 3/4/5)

    week 3 Classification KNN :基本思想是 input value 类似,就可能是同一类的 Decision Tree Naive Bayes Week 4 Evaluating ...

  3. EL表达式 - 日常使用表达式记录

    表达式 说明 ${field} 查找域,page ->request -> session -> application 中的值. ${field == null ? field1: ...

  4. iOS 集成百度地图 位置偏移问题

    iOS 集成百度SDK 请参考 百度地图官方文档 ,这里不就多啰嗦了 本文介绍的是在百度地图上根据经纬度,自定义气泡时,气泡位置的偏移,在我们天朝这种事是很常见的,也见怪不怪了,在项目中使用的百度地图 ...

  5. 2018-2019 20165221 网络对抗 Exp5 MSF基础

    2018-2019 20165221 网络对抗 Exp5 MSF基础 实践内容: 重点掌握metassploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 一个主动攻击实践,如ms0 ...

  6. 基于Python的Webservice开发(三)-Django安装配置

    一.安装Django pip install django 二.创建项目 进入指定的目录后 django-admin startproject WebApi 目录说明: WebApi 项目的容器. m ...

  7. stat 文件三个时间点

    Linux文件3个时间点(access time,modify time,change time) access time:表示最后一次访问(仅仅是访问,没有改动)文件的时间. 注意:至于为什么会出现 ...

  8. 题解-POI2014 Supercomputer

    Problem 辣鸡bzoj权限题,洛谷链接 题意概要:一棵 \(n\) 个点有根树.\(Q\) 次询问给出一个 \(K\),回答遍历完整棵树所需最少操作次数.每次操作可以选择访问不超过 \(K\) ...

  9. Java线程池(待续)

    线程池是预先创建线程的一种技术..线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中.这些线程都是处于睡眠状态,即均为启动,不消耗CPU,而只是占用较小的内存空间.当请求到来之后,缓冲池给 ...

  10. 写一个python脚本监控在linux中的进程

    在虚拟机中安装Linux中的CentOS7系统 https://baijiahao.baidu.com/s?id=1597320700700593557&wfr=spider&for= ...