思路
- 从题意来看明显可以使用宽搜
- 但是也可以从集合的角度应用并查集求解(从大佬的博客受到启发)
- 将能连在一起的洞看作一个集合
- 最后判断是否有一对通向底部并且通向顶部的点在同一个集合
- 有的话即课满组题意所需条件
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
typedef long long ll;
ll n, m, t;
ll x[N], y[N], z[N];
ll p[N];
ll f1[N], f2[N];
ll findx(ll x)
{
if(p[x] != x) p[x] = findx(p[x]);
return p[x];
}
ll get_dist(ll a1, ll a2, ll a3, ll b1, ll b2, ll b3)
{
return (a1 - b1) * (a1 - b1) + (a2 - b2) * (a2 - b2) + (a3 - b3) * (a3 - b3);
}
int main()
{
cin >> t;
while(t --)
{
ll n, h, r;
cin >> n >> h >> r;
ll top = 0, bom = 0;
for(ll i = 1; i <= n; i ++) p[i] = i;
for(ll i = 1; i <= n; i ++)
{
cin >> x[i] >> y[i] >> z[i];
if(z[i] - r <= 0)
{
f1[bom ++] = i;
}
if(z[i] + r >= h)
{
top ++;
f2[top ++] = i;
}
for(ll j = 1; j <= i; j ++)
{
if((x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]) > 4 * r * r) continue;
if(get_dist(x[i], y[i], z[i], x[j], y[j], z[j]) <= 4 * r * r)
{
ll a = findx(i), b = findx(j);
if(a != b) p[a] = b;
}
}
}
ll s = 0;
for(ll i = 0; i < top; i ++)
{
for(ll j = 0; j < bom; j ++)
{
if(findx(f1[j]) == findx(f2[i]))
{
s = 1;
break;
}
}
if(s) break;
}
if(s) puts("Yes");
else puts("No");
}
return 0;
}
|