标签:add ace name alt break ima strong flow const
首先当然是二分,
然后对于一个点而言,它可以到达的区域是一个圆弧。
现在就是问有没有一种正多边形的端点可以被这些圆弧覆盖。
假设现在存在一种可行的方案,如果这个正多边形没有一个端点与某一个圆弧的一个端点重合的话,
那么我可以抖动这个正多边形直到其的一个端点与某一个圆弧的一个端点重合为止,
这个我是想说,如果存在可行的方案,那么一定存在一种可行的方案,使得该正多边形有一个端点与某个圆弧的一个端点重合。
由于圆弧的端点的个数有\(O(n)\),所以这个枚举重合的那个端点,然后就可以通过这个端点确定正多边形的其他端点。
然后就可以建出二分图,问是否有完美匹配了。
复杂度是\(O(n^4*logn)\)的,可以过50分。
坑待填。
#include<bits/stdc++.h>
#define ll long long
#define db double
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define fd(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const int maxn=407,maxm=maxn*maxn;
const db pi=acos(-1);
int n,m;
db Step;
struct P{
int x,y;
}a[maxn];
void Init(){
scanf("%d%d",&n,&m);
fo(i,1,n) scanf("%d%d",&a[i].x,&a[i].y);
Step=2*pi/n;
}
int N;
db q[maxn*2],L[maxn],R[maxn];
void newQuery(db x){
while (x>=-pi+Step) x-=Step;
while (x<-pi) x+=Step;
q[++N]=x;
}
int fi[maxn],ne[maxm],la[maxm],va[maxm],tot,T;
void add(int a,int b,int c){
tot++;
ne[tot]=fi[a];
la[tot]=b;
va[tot]=c;
fi[a]=tot;
}
void Add(int a,int b,int c){
add(a,b,c);
add(b,a,0);
}
int bz[maxn],id;
int sap(int v,int flow){
bz[v]=id;
if (v==T) return flow;
for(int k=fi[v];k;k=ne[k])
if (bz[la[k]]<id && va[k]){
int i=sap(la[k],min(va[k],flow));
if (i){
va[k]-=i;
va[k^1]+=i;
return i;
}
}
return 0;
}
bool check(db ang){
db y=ang;
tot=1;
memset(fi,0,sizeof fi);
fo(i,1,n){
fo(j,1,n){
if (L[j]>R[j] && (L[j]<=y && y<=R[j]+pi*2 || L[j]-pi*2<=y && y<=R[j]) || L[j]<=R[j] && L[j]<=y && y<=R[j]){
Add(1+j,1+n+i,1);
}
}
y+=Step;
}
fo(i,1,n) Add(1,1+i,1);
T=2+n+n;
fo(i,1,n) Add(1+n+i,T,1);
int res=0;
while (1){
id++;
int temp=sap(1,0x7fffffff);
if (!temp) break;
res+=temp;
}
return res>=n;
}
bool judge(db rad){
N=0;
fo(i,1,n){
db Dist=sqrt(a[i].x*a[i].x+a[i].y*a[i].y);
if (rad+m<Dist || Dist<m-rad || a[i].x==0 && a[i].y==0 && rad<m) return false;
if (rad<m+Dist){
db Alpha=atan2(a[i].y,a[i].x),Beta=acos((m*m+Dist*Dist-rad*rad)/(2.0*m*Dist));
L[i]=Alpha-Beta;
R[i]=Alpha+Beta;
if (L[i]<-pi) L[i]+=2*pi;
if (R[i]>=pi) R[i]-=2*pi;
}else{
L[i]=-pi;
R[i]=pi;
}
newQuery(L[i]);
newQuery(R[i]);
}
sort(q+1,q+N+1);
fo(i,1,N) if ((i==1 || q[i]-q[i-1]>1e-7) && check(q[i])) return true;
return false;
}
db Ans;
void Solve(){
db l=0,r=100;
while (r-l>1e-9){
db mid=(l+r)/2;
if (judge(mid)) r=mid;
else l=mid;
}
Ans=l;
}
void Print(){
printf("%.8lf\n",Ans);
}
int main(){
freopen("3.in","r",stdin);
freopen("3.out","w",stdout);
Init();
Solve();
Print();
return 0;
}
标签:add ace name alt break ima strong flow const
原文地址:https://www.cnblogs.com/hiweibolu/p/9048012.html