Star Way To Heaven

以考虑二分答案r,对k个star都建一个半径为r的圆,那么对于两个相交的圆把它们弄到一个集合,对上下边界特殊判断,如果说上下边界被弄到了一个集合,即说明,有若干个圆将矩形拦腰折断,分成了两个不连通的部分,则这个答案不合法。
由此得到prim算法,现将一个边界加入集合,找到距离它最小的点,加入集合,将与之相连的点的距离更新
如此加边,知道另一边界也加入集合中,此时刚好上下界拦腰截断,其实这时的maxdis为恰好不能走过去时的最小dis,那么只要小一点点,就符合了,那么精度就没事了

#include<cstdio>
#include<cctype>
#include<cmath>
#include<algorithm>
#define min(a, b) ((a)<(b)?(a):(b))
#define max(a, b) ((a)>(b)?(a):(b))
using namespace std;
const int maxn=6005;
int n,m,k,x[maxn],y[maxn];
double dis[maxn],ans;
bool vis[maxn];
inline double cal(int a1,int a2,int b1,int b2){return sqrt((double)(a1-b1)*(a1-b1)+(double)(a2-b2)*(a2-b2));}
inline void read(int &x){
    char ch=getchar();x=0;
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
}
int main(){
    read(n);read(m);read(k);
    for(int i=1;i<=k;i++){read(x[i]);read(y[i]);}
    for(int i=1;i<=k;i++)dis[i]=y[i];dis[k+1]=m;dis[0]=2e9;
    while(1){
        int minn=0;
        for(int i=1;i<=k+1;i++)if(!vis[i] && dis[i]<dis[minn])minn=i;
        ans=max(ans,dis[minn]);
        if(minn==k+1)return printf("%.8lf",ans/2.0),0;
        for(int i=1;i<=k;i++)dis[i]=min(dis[i],cal(x[i],y[i],x[minn],y[minn]));
        dis[k+1]=min(dis[k+1],m-y[minn]);
        vis[minn]=1;
    }
    return 0;
}

 

posted @ 2018-07-02 17:08  lnyzo  阅读(393)  评论(0编辑  收藏  举报