奶酪(NOIP2017 Day2 T1)

这应该是NOIP2017除了T1我思路最清楚的一道题了
(大概是因为我太菜了吧)
具体的见代码注释(写的比较laji,凑合着看吧)

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=1e4+5;
int t,n,h;
long long r;//好大的洞 
long long x[maxn],y[maxn],z[maxn];
int fa[maxn],down[maxn],top[maxn];//down和top分别记录触到底部和顶部的洞编号 
bool flag=1;
int find(int x){//并茶几 
	if(x!=fa[x]) fa[x]=find(fa[x]);
	return fa[x];	 
}
void Dofind(int x,int y){//合并 
	int f1=find(x),f2=find(y);
	if(f1!=f2) fa[f1]=f2;
}
double Dist(long long x1,long long y1,long long z1,long long x2,long long y2,long long z2){//计算距离 
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%lld",&n,&h,&r);
		int cnt1=0,cnt2=0;//cnt1与洞顶相交的点数,cnt2与洞底相交点数 
		for(int i=1;i<=n;i++) fa[i]=i;//初始化 
		for(int i=1;i<=n;i++){
			scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);//不得不说这个洞真大 
			if(z[i]+r>=h){//触到顶部的洞 
				cnt1++;
				top[cnt1]=i;
			}
			if(z[i]-r<=0){//触到底部的洞 
				cnt2++;
				down[cnt2]=i;
			}
			for(int j=1;j<=i;j++){
				if(Dist(x[i],y[i],z[i],x[j],y[j],z[j])<=2*r){
					Dofind(i,j);//洞的距离小于2*半径r就能连通 
				}
			}
		}
		flag=0;
		for(int i=1;i<=cnt1;i++){
			for(int j=1;j<=cnt2;j++){
				if(find(top[i])==find(down[j])){// 
					flag=1;break;
				}
			}
			if(flag==1) break;
		}
		if(flag) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
} 
> ``` 
posted @ 2018-11-08 21:37  Dzzzzzz  阅读(135)  评论(0编辑  收藏  举报