题目
思路
伊艳二分
这个题比较难的地方就是如何判断在当前r的情况下能否到达终点
我们可以用并查集来判断两个点是否连接,再加两个点:0和n+1
代码
#include<bits/stdc++.h>
using namespace std;
#define _p(x) ((x)*(x))
const int maxn=3005;
const double eps=1e-5;
int n;
double r,c;
int bx[maxn],by[maxn];
int f[maxn];
double ans;
int find(int x) { return f[x]==x?x:f[x]=find(f[x]); }
void init(int n) { for(int i=0;i<=n;i++) f[i]=i; }
void merge(int u,int v) { int x=find(u),y=find(v);if(x!=y) f[x]=y; }
int dis(int i,int j) { return _p(bx[i]-bx[j])+_p(by[i]-by[j]); }
bool check(double r){
init(n+1);
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++) if(dis(i,j)<=_p(2*r)) merge(i,j);//是否能绕过
if(bx[i]-r<=1||by[i]+r>=c) merge(i,0);//起点
if(bx[i]+r>=::r||by[i]-r<=1) merge(i,n+1);//重点
}
return find(0)!=find(n+1);//能否到达
}
int main()
{
cin>>n>>r>>c;
for(int i=1;i<=n;i++) cin>>bx[i]>>by[i];
double l=0,r=min(::r,c);
while(r-l>eps){
double mid=(l+r)/2;
if(check(mid)) l=mid,ans=mid;
else r=mid;
}
printf("%.2lf",ans);
return 0;
}