一个比较好想的暴力:
二分答案,然后把每艘飞船的能到达的距离算出,是一个圆,把所有圆和攻击轨道求交,相交这段弧和多边形顶点可以匹配,可以发现一定有个多边形顶点在某个交点处
那么就枚举这个顶点,然后
(
O
(
n
2
)
)
(O(n^2))
(O(n2))连边,跑
d
i
n
i
c
dinic
dinic是
O
(
e
e
)
O(e\sqrt e)
O(ee)
总复杂度
O
(
n
4
l
o
g
n
)
O(n^4logn)
O(n4logn)
如何优化?我们发现每次转一个角度,每个点都会少一个匹配区间,多一个匹配区间,所以排序后维护退流就可以少一个 n n n
Code:
#include<bits/stdc++.h>
#define eps 1e-9
#define db double
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)){res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=610,M=100010,inf=1e9;
const db pi=acos(-1);
int n,s,t,pt[N],Head[N],tot,cur[N],d[N],que[N],head,top,flow,cnt;
db rr,de;
struct Edge{int v,nxt,f;}E[M<<1];
struct point{db x,y;}p[N];
db dis(point A){return sqrt(A.x*A.x+A.y*A.y);}
struct data{
db the;int u,v,t;
data(db _the=0,int _u=0,int _v=0,int _t=0):the(_the),u(_u),v(_v),t(_t){};
bool operator <(const data&A)const{return the==A.the?t>A.t:the<A.the;}
}q[N];
inline bool bfs(){
for(int i=s;i<=t;i++) pt[i]=0,cur[i]=Head[i];
head=top=0;pt[que[++top]=s]=d[s]=1;
while(head<top){
int u=que[++head];
for(int i=Head[u];~i;i=E[i].nxt)
if(E[i].f){
int v=E[i].v;
if(pt[v]) continue;
pt[v]=1;d[v]=d[u]+1;que[++top]=v;
if(v==t) return true;
}
}
return false;
}
int dfs(int u,int c){
if(u==t || !c)return c;
int flow=0,f;
for(int i=cur[u];~i;i=E[i].nxt){
int v=E[cur[u]=i].v;
if(d[v]==d[u]+1&&(f=dfs(v,min(E[i].f,c)))){
flow+=f;c-=f;
E[i].f-=f;E[i^1].f+=f;
if(!c) break;
}
}
return flow;
}
inline void add(int u,int v){
E[tot]=(Edge){v,Head[u],1};Head[u]=tot++;
E[tot]=(Edge){u,Head[v],0};Head[v]=tot++;
}
inline void delta(int u,int v){
int f=0;
for(int i=Head[u];~i;i=E[i].nxt)if(E[i].v==v){
if(!E[i].f)flow--;else f=1;
E[i].f=E[i^1].f=0;
break;
}
if(f)return;
for(int i=Head[s];~i;i=E[i].nxt)if(E[i].v==u){E[i].f=1;E[i^1].f=0;break;}
for(int i=Head[v];~i;i=E[i].nxt)if(E[i].v==t){E[i].f=1;E[i^1].f=0;break;}
if(bfs()) flow+=dfs(s,inf);
}
bool check(db mid){
flow=cnt=tot=0;
for(int i=s;i<=t;i++) Head[i]=-1;
for(int i=1;i<=n;i++){
db d=dis(p[i]);
if(mid+d<=rr || mid+rr<=d) return false;
if(rr+d<=mid){
for(int j=1;j<=n;j++) add(i,j+n);
continue;
}
db the=atan2(p[i].y,p[i].x);
db delta=acos((d*d+rr*rr-mid*mid)/(2*d*rr));
db the1=the-delta,the2=the+delta;
while(the1<0) the1+=pi*2;
while(the2<0) the2+=pi*2;
int l=the1/de,r=the2/de;
the1=the1-de*l;
the2=the2-de*r;
l++;r++;
q[++cnt]=(data){the1,i,l,1};
q[++cnt]=(data){the2,i,r,-1};
if(l<=r)for(int j=l+1;j<=r;j++) add(i,j+n);
else{
for(int j=1;j<=r;j++) add(i,j+n);
for(int j=l+1;j<=n;j++) add(i,j+n);
}
}
sort(q+1,q+cnt+1);
for(int i=1;i<=n;i++) add(s,i),add(i+n,t);
while(bfs()) flow+=dfs(s,inf);
if(flow==n) return true;
for(int i=1;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 delta(q[i].u,q[i].v+n);
}
return false;
}
int main(){
n=read(),rr=read();
de=2*pi/n;s=0,t=n*2+1;
for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
db l=0,r=200;
while(r-l>eps){
db mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
printf("%.8lf\n",l+eps);
return 0;
}