码迷,mamicode.com
首页 > Web开发 > 详细

【JSOI2018】绝地反击

时间:2018-05-16 22:29:17      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:add   ace   name   alt   break   ima   strong   flow   const   

题面

技术分享图片

50pts

首先当然是二分,
然后对于一个点而言,它可以到达的区域是一个圆弧。
现在就是问有没有一种正多边形的端点可以被这些圆弧覆盖。
假设现在存在一种可行的方案,如果这个正多边形没有一个端点与某一个圆弧的一个端点重合的话,
那么我可以抖动这个正多边形直到其的一个端点与某一个圆弧的一个端点重合为止,
这个我是想说,如果存在可行的方案,那么一定存在一种可行的方案,使得该正多边形有一个端点与某个圆弧的一个端点重合。
由于圆弧的端点的个数有\(O(n)\),所以这个枚举重合的那个端点,然后就可以通过这个端点确定正多边形的其他端点。
然后就可以建出二分图,问是否有完美匹配了。
复杂度是\(O(n^4*logn)\)的,可以过50分。

100pts

坑待填。

代码

#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;
}

【JSOI2018】绝地反击

标签:add   ace   name   alt   break   ima   strong   flow   const   

原文地址:https://www.cnblogs.com/hiweibolu/p/9048012.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!