奶酪(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;
}
> ```