T428497 请不要抢走爱丽丝的工作! 题解
T428497 请不要抢走爱丽丝的工作! 题解

本题要求扫地机器人半径 \(r\) 的最大值,既然要求最大值,容易想到二分答案。
那问题就转换为给定半径 \(R\) , 判断 \(R\) 满不满足条件,也就是能不能找到一条绕过所有障碍的路径。让我们逆转一下思维,考虑哪些区域是机器人不能到达的。简单分析就能得到以下结论:
- 与边界的距离小于 \(R\) 的点是不能到达的,这些点形成了一个矩形区域
- 与某一个障碍物的距离小于 \(R\) 的点是不能到达的,这些点形成了一个圆形区域
把这些区域全都画出来,如果发现上边界和下边界被这些区域连到一起了,就说明不存在能绕过这些不可达区域的路径,反之则存在。
分析到这里显然是要用并查集来判断上边界和下边界是否连通了,如果某个障碍物与边界的距离小于 \(2\times{R}\) ,则将此障碍物与边界相连, 如果两个障碍物之间的距离小于 \(2\times{R}\),则将这两个障碍物相连。以下是AC代码:
#include <bits/stdc++.h>
#define MAXN 105
using namespace std;
int px[MAXN];
int py[MAXN];
double dis[MAXN][MAXN];
int pre[MAXN];
int root(int x){
return pre[x] = pre[x]==x?x:(root(pre[x]));
}
void merge(int x,int y){
x = root(x);
y = root(y);
if(x!=y) pre[x] = y;
}
bool check(double m,int n){
memset(pre,0,sizeof(pre));
for(int i=0;i<MAXN;i++) pre[i] = i; // 101号设为上边界, 102号设为下边界
for(int i=0;i<n;i++){
if(100.0-py[i]<2*m) merge(101,i);
if(py[i]+100.0<2*m) merge(102,i);
}
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(dis[i][j]<2*m) merge(i,j);
}
}
if(root(101)==root(102)) return true;
else return false;
}
void solve(){
int n;
cin >> n;
memset(px,0,sizeof(px));
memset(py,0,sizeof(py));
memset(dis,0,sizeof(dis));
for(int i=0;i<n;i++){
cin >> px[i] >> py[i];
}
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
dis[i][j] = dis[j][i] = sqrt(pow(px[i]-px[j],2)+pow(py[i]-py[j],2));
}
}
double l = 0, r = 100, lm = 10000;
while(l<=r){
double m = (l+r)/2;
if(abs(lm-m)<1e-6) break;
lm = m;
if(check(m,n)){
r = m;
}else{
l = m;
}
}
cout << lm;
}
int main(){
int t = 1;
// cin >> t;
while(t--){
solve();
}
}

浙公网安备 33010602011771号