zoukankan      html  css  js  c++  java
  • Luogu P4518 [JSOI2018]绝地反击

    Link
    假如我们现在确定了一个答案,然后要检测它是否可行。
    我们求出所有飞船能够到达的圆弧,总共有(2n)个端点。
    如果存在一组合法解,那么一定存在一组正多边形有至少一个顶点在端点上的解,那么我们暴力建边然后求二分图最大匹配即可。
    利用爬山+二分优化即可通过。
    正解大概是说首先圆弧对应的偏转角度可以(mod frac{2pi}n),然后用退流优化dinic做到(O(n^3log n))

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<utility>
    #include<algorithm>
    using ld=long double;
    using pi=std::pair<ld,ld>;
    const int N=207;const ld eps=1e-10,PI=acos(-1);
    int n,R,mat[N],vis[N],e[N][N];pi w[N],b[N];
    struct node{int x,y;ld d;node(int a=0,int b=0):x(a),y(b),d(sqrt(a*a+b*b)){}}a[N];
    int read(){int x;scanf("%d",&x);return x;}
    int sgn(ld x){return x>eps? 1:x<-eps? -1:0;}
    ld sqr(ld x){return x*x;}
    ld Bonus_solve(){ld ans=0;for(int i=0;i<n;++i) ans=std::max(ans,a[i].d);return ans;}
    int dfs(int u)
    {
        for(int v=0;v<n;++v) if(!vis[v]&&e[u][v]) if(vis[v]=1,!~mat[v]||dfs(mat[v])) return mat[v]=u,1;
        return 0;
    }
    int check(int id,int flg,ld r)
    {
        ld l=(sqr(a[id].x)+sqr(a[id].y)+r-R*R)/(2*a[id].d),h=sqrt(std::max((ld)0,r-l*l));
        ld dx=-a[id].x/a[id].d,dy=-a[id].y/a[id].d,px=a[id].x+dx*l,py=a[id].y+dy*l;
        dy=-dy,std::swap(dx,dy),dx*=h,dy*=h,px-=flg*dx,py-=flg*dy,b[0]=pi(px,py),memset(mat,-1,4*n);
        for(int i=1;i<n;++i) b[i]=pi(px*w[i].second-py*w[i].first,px*w[i].first+py*w[i].second);
        for(int i=0;i<n;++i) for(int j=0;j<n;++j) e[i][j]=sgn(sqr(a[i].x-b[j].first)+sqr(a[i].y-b[j].second)-r)<=0;
        for(int i=0;i<n;++i) if(memset(vis,0,4*n),!dfs(i)) return 0;
        return 1;
    }
    int main()
    {
        n=read(),R=read();ld ans=0,lim=0;
        for(int i=0,x,y;i<n;++i) x=read(),y=read(),a[i]=node(x,y);
        if(!R) return !printf("%.10Lf",Bonus_solve());
        for(int i=1;i<n;++i) w[i]=pi(sin(2*PI*i/n),cos(2*PI*i/n));
        std::random_shuffle(a,a+n);
        for(int i=0;i<n;++i) lim=std::max(lim,sqr(a[i].x)+sqr(a[i].y)<=R+eps? R-a[i].d:a[i].d-R),ans=std::max(ans,a[i].d+R);
        for(int i=0;i<n;++i)
        {
    	if(!a[i].x&&!a[i].y) continue;
    	for(int j:{-1,1})
    	{
    	    ld l=lim,r=std::max(std::min(a[i].d+R,ans-eps),lim);
    	    if(!check(i,j,sqr(r))) continue;
    	    for(ld mid;l+eps<r;) mid=(l+r)/2,check(i,j,sqr(mid))? r=ans=mid:l=mid;
    	}
        }
        printf("%.10Lf",ans);
    }
    
  • 相关阅读:
    orapwd创建密码文件
    ORA-00119: invalid specification for system parameter LOCAL_LISTENER
    创建和使用虚拟专用目录
    创建和使用RMAN存储脚本
    oracle归档日志管理
    Flash Recovery Area 的备份
    Flash Recovery Area空间不足导致DB不能打开或hang住处理方法
    Flash Recovery Area
    计算机组成原理实验之微程序控制器实验
    面向对象程序设计(OOP设计模式)-行为型模式之观察者模式的应用与实现
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/13062505.html
Copyright © 2011-2022 走看看