C. Safe Distance
题意:
给出一个 X * Y 大小的矩形
有
n
n
n 个人,每个人都在矩阵某个位置
求从左下角
0
,
0
0,0
0,0 走到
X
,
Y
X,Y
X,Y 这个过程中,与人的距离的最大值
思路:
读题我们可以,我们需要使得最小距离最大化,可以想到二分答案
难点在于我们该如何写
c
h
e
c
k
check
check
如果能想到这种处理方式,题目就迎刃而解了(感觉很难想
把每个人看成以
m
i
d
mid
mid 为半径的圆
用并查集维护连通性,检查边界是否有通过人连接起来的,如果有就说明当前的
m
i
d
mid
mid 太大,不符合
因为是从左下走到右上
所以检查上下,上右,下左,左右这四个是否有连接起来的即可
注意和边界如何判断是否相交,大佬写的比较奇妙
也可以先暴力合并完
n
n
n 个点,最后再合并边界
这道题让我发现了一个神奇的事情
n
n
n 开
l
l
ll
ll 会比开
i
n
t
int
int 慢接近一倍
l
l
ll
ll 的存在会跑的更慢
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define epc 1e-5
using namespace std;
const int maxn = 1e3 + 9;
const int mod = 1e9 + 7;
ll n, m;
int X, Y;
double a[maxn], b[maxn];
int f[maxn];
int find(int x){
return f[x] == x ? x : f[x] = find(f[x]);
}
bool check(double mid)
{
for(int i = 1; i <= n + 4; ++i) f[i] = i;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n + 4; ++j)
{
if(i == j) continue;
if(j == n + 1 || j == n + 2) a[j] = a[i];// 固定行不动,求与上下边界的距离
if(j == n + 3 || j == n + 4) b[j] = b[i];// 固定列不动,求与左右边界的距离
double dis = sqrt((a[i]-a[j])*(a[i]-a[j]) + (b[i]-b[j])*(b[i]-b[j]));
if(j <= n && dis < 2 * mid || j > n && dis < mid)
{
int pa = find(i), pb = find(j);
f[pa] = pb;
}
}
if(find(n + 1) == find(n + 2)) return 0;// 下上
if(find(n + 1) == find(n + 3)) return 0;// 下左
if(find(n + 3) == find(n + 4)) return 0;// 左右
if(find(n + 2) == find(n + 4)) return 0;// 上右
return 1;
}
void work()
{
cin >> X >> Y >> n;
for(int i = 1; i <= n; ++i) cin >> a[i] >> b[i];
b[n + 1] = 0;
// 下边界
b[n + 2] = Y;
// 上边界
a[n + 3] = 0;
// 左边界
a[n + 4] = X;
// 右边界
double l = 0, r = 1e6;
for(int i = 1; i <= 40; ++i)
{
//cout << i << endl;
double mid = (l + r) / 2;
if(check(mid)) l = mid;
else r = mid;
}
cout << l << endl;
}
int main()
{
ios::sync_with_stdio(0);
//int TT;cin>>TT;while(TT--)
work();
return 0;
}