思想是并查集记录的是从一个点开始能到达的最高的点(就是球心),最后找一下谁在底下,再看一下并查集有没有和顶上的球相交
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=1e3+5;
ll T;
ll n,h,r;
ll x[N],y[N],z[N];
ll f[N];//并查集
//存储第i个点表示的圆所能到达的最上面的圆
ll get(ll x){
if(x==f[x]) return x;
return f[x]=get(f[x]);
}
void merge(ll x,ll y){
f[get(x)]=get(y);
}
ll dis(ll x1,ll y1,ll z1,ll x2,ll y2,ll z2){
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2);
}
int main(){
scanf("%lld",&T);
while(T--){
cin>>n>>h>>r;
for(int i=1;i<=n;++i){
scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
f[i]=i;//初始化
}
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
if(dis(x[i],y[i],z[i],x[j],y[j],z[j])<=2*2*r*r){
//两球相交
if(z[i]>z[j]) merge(j,i);//j并到i上
else merge(i,j);
}
}
}
bool went=false;
for(int i=1;i<=n;++i){
if(r>=z[i] and z[i]>=-r){//是底边的球心
if(z[f[i]]<=r+h and z[f[i]]>=h-r){//连接
cout<<"Yes\n";
went=true;
break;
}
}
}
if(!went) cout<<"No\n";
//判断能不能走到
}
return 0;
}