60分求帮忙,临表涕零,不知所言
查看原帖
60分求帮忙,临表涕零,不知所言
467941
CChara_std楼主2024/7/22 19:26

思想是并查集记录的是从一个点开始能到达的最高的点(就是球心),最后找一下谁在底下,再看一下并查集有没有和顶上的球相交

#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;
}
2024/7/22 19:26
加载中...