二分+並查集【bzoj3007】[SDOI2012]拯救小云公主

Description

英雄又即將踏上拯救公主的道路……ios

此次的拯救目標是——愛和正義的小云公主。git

英雄來到boss的洞穴門口,他一會兒就懵了,由於面前不僅是一隻boss,而是上千只boss。當英雄意識到本身仍是等級1的時候,他明白這就是一個不可能完成的任務。spa

但他不死心,他在想,能不能避開boss去拯救公主呢,嘻嘻。code

Boss的洞穴能夠當作一個矩形,英雄在左下角(1,1),公主在右上角(row,line)。英雄爲了避開boss,固然是離boss距離越遠越好了,因此英雄決定找一條路徑使到距離boss的最短距離最遠。ip

Ps:英雄走的方向是任意的。get

你能夠幫幫他嗎?input

當英雄找到了美麗漂亮的小云公主,馬上就被boss包圍了!!!英雄緩閉雙眼,舉手輕揮,白光一閃後使用了回城卷軸,回到了城堡,但只有小云公主回去了……由於英雄忘了進入回城的法陣了。it

Input

第一行,輸入三個整數,n表示boss的數目,row,line表示矩形的大小;io

接下來n行,每行分別兩個整數表示boss的位置座標。class

Output

輸出一個小數,表示英雄的路徑離boss的最遠距離,精確到小數點後兩位。

這裏的距離指的是歐幾里德距離

首先很容易看出是二分答案

咱們能夠當作是以每一個\(boss\)爲圓心做一個半徑爲\(r\)的圓,咱們想要求的就是讓這些圓儘量大,而且不能影響咱們從\((1,1)\)\((n,m)\)。(不能覆蓋)

直接考慮邊界條件\((n,1)\)\((1,m)\)若是這兩個點沒有被覆蓋,那我必然能夠到達\((n,m)\)

PS:這裏的判斷條件不是同時判斷。

這樣用\(||\)判斷,能夠達到咱們邊界不被封鎖的狀況。

並查集維護連通便可。

代碼

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define eps 1e-4
#define R register

using namespace std;

const int gz=3e3+8;

inline void in(R int &x)
{
    R int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}

int nn,n,m,f[gz];

struct cod
{
    int x,y;
}bos[gz];

int find(R int x){return f[x]==x?x:f[x]=find(f[x]);}

inline double xx(R double x)
{
    return x*x;
}

inline double dis(R int i,R int j)
{
    return xx(bos[i].x-bos[j].x)+xx(bos[i].y-bos[j].y);
}

inline bool ok(R double r)
{
    for(R int i=0;i<=nn+1;i++)f[i]=i;
    for(R int i=1;i<=nn;i++)
    {
        for(R int j=1;j<i;j++)
        {
            if(dis(i,j)<=xx(2*r))
            {
                R int fa=find(i),fb=find(j);
                if(fa!=fb)f[fa]=fb;
            }
        }
        if(bos[i].x-r<=1 or bos[i].y+r>=m)
        {
            R int fa=find(i),fb=find(0);
            if(fa!=fb)f[fa]=fb;
        }
        if(bos[i].x+r>=n or bos[i].y-r<=1)
        {
            R int fa=find(i),fb=find(nn+1);
            if(fa!=fb)f[fa]=fb;
        }
    }
    return find(0)!=find(nn+1);
}

int main()
{
    in(nn),in(n),in(m);
    for(R int i=1;i<=nn;i++)
        in(bos[i].x),in(bos[i].y);
    R double ll=0,rr=min(n,m);
    while(fabs(ll-rr)>eps)
    {
        R double mid=(ll+rr)/2;
        if(ok(mid))ll=mid;
        else rr=mid;
    }
    printf("%.2f",ll);
}
相關文章
相關標籤/搜索