• [二分][并查集] Jzoj P5904 刺客信条(AC)


    Description

              故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一名刺客。最终,凭借着他的努力和出众的天赋,成为了杰出的刺客大师。刺客组织在他的带领下,为被剥削的平民声张正义,赶跑了原本统治意大利的圣殿骑士首领-教皇亚历山大六世。在他的一生中,经历了无数次惊心动魄、扣人心弦的探险和刺杀。
            这次的故事就是他暗杀一位作恶多端的红衣主教。红衣主教可以吸取他周围人的生命力量,而他的红衣教徒也拥有这个力量。红衣主教的家是一个x*y 的长方形房间,也就是说,他的家的四个角坐标分别为(0,0)(x,0)(0,y)(x,y)。教堂的门在(0,0) ,而红衣主教就在 (x,y)的卧室休息。他的家中还有n个守护着他的红衣教徒,站在(ai,bi)。Ezio想要趁主教休息时,从门进入潜入到他的卧室刺杀他,因为主教休息时会脱下红衣,这样吸取生命的力量就消失了。可是守卫他的红衣教徒依然很危险,离红衣教徒太近就会被吸取生命。因此,Ezio想知道,在能刺杀主教的前提,从门到他的卧室的路上,他最远和离他最近的红衣教徒保持多远的距离。注意:教徒都在房间里。
     

    Input

    第一行三个整数x,y,n。之后n行,每行两个整数ai,bi ,意义见题目描述。

    Output

    一行一个数D,表示Ezio能保持的最大距离,保留两位小数。
     

    Sample Input

    10 20 2
    3 3
    6 14

    Sample Output

    3.00
    
    
    
    样例说明
    贴着墙走
     

    Data Constraint

    数据范围
    对 10%的数据n<=10,
     对 30%的数据n<=100
    对 100%的数据n<=2000
    保证输入合法,x,y属于[1,10^6].

    题解

    • 如果,换个思路想想,我们把可以相通的点合并,那么最后只用判断能否有一条路经过
    • 然后二分一个长度,以每个点为圆心画圆,将不能联通的放在同一个并查集内
    • 那么如果左边的墙和下面的墙在同一个并查集内的话,那么就是不可能过去的嘛
    • 还有就是上和下,下和右,上和左某一组在同一个并查集内的话,就无法从(0,0)到(x,y),感性理解一下

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 using namespace std;
     5 const double eps=1e-4;
     6 int n,fa[2010];
     7 double l,r,ans,a[2010],b[2010],x,y;
     8 int getfather(int x) { return !fa[x]?x:fa[x]=getfather(fa[x]); }
     9 double sqr(double x) { return x*x; }
    10 void merge(int x,int y)
    11 {
    12     int u=getfather(x),v=getfather(y);
    13     if (u!=v) fa[u]=v;
    14 }
    15 bool check(double d)
    16 {
    17     memset(fa,0,sizeof(fa));
    18     for (int i=1;i<=n;i++)
    19     {
    20         if (a[i]<=d) merge(i,n+1);
    21         if (b[i]<=d) merge(i,n+2);
    22         if (a[i]+d>=x) merge(i,n+3);
    23         if (b[i]+d>=y) merge(i,n+4);
    24     }
    25     for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) if (sqr(a[i]-a[j])+sqr(b[i]-b[j])<=4*d*d) merge(i,j);
    26     if (getfather(n+1)==getfather(n+2)) return false;if (getfather(n+1)==getfather(n+3)) return false;
    27     if (getfather(n+2)==getfather(n+4)) return false;if (getfather(n+3)==getfather(n+4)) return false;
    28     return true;
    29 }
    30 int main() 
    31 {
    32     freopen("AC.in","r",stdin),freopen("AC.out","w",stdout);
    33     scanf("%lf%lf%d",&x,&y,&n);
    34     for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i],&b[i]);
    35     l=0,r=1e6;
    36     while (r-l>=eps)
    37     {
    38         double mid=(l+r)/2;
    39         if (check(mid)) ans=mid,l=mid+eps; else r=mid;
    40     }
    41     printf("%.2lf",ans);
    42 }
  • 相关阅读:
    UOJ 【UR #5】怎样跑得更快
    【TJOJIHEOI2016】求和
    CF 932E Team Work
    【BZOJ2159】Crash的文明世界
    Luogu P4707 重返现世
    Luogu P3175 [HAOI2015]按位或
    【BZOJ3930】选数
    nginx 学习
    如何解决 react-create-app 里面的 no-unused-vars ?
    随时更新web html 项目页面,查看手机等其他移动设备的几种方法?
  • 原文地址:https://www.cnblogs.com/Comfortable/p/9794226.html
Copyright © 2020-2023  润新知