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