就是一道并查集问题,写起来也不算麻烦,而且数据范围比较优秀,可以满足O(n^2)的做法。
思路也很容易形成:
先合并所有洞,再找最下面有没有洞。找的过程中,再判断能不能到达最顶层就好了。(反正也没问最短路线不是嘛~ :^) )
代码:
#include<cstdio> #include<cmath> using namespace std; #define int long long int T,n,h,r; int a,b,c; bool flag; int par[1010]; struct xyz { int x,y,z; } s[1010]; double dis(int x,int y,int z,int nx,int ny,int nz) { return sqrt((x-nx)*(x-nx)+(y-ny)*(y-ny)+(z-nz)*(z-nz)); } int find(int xx) { if(xx==par[xx]) return xx; else return par[xx]=find(par[xx]); } void merge(int xx,int yy) { par[find(xx)]=find(yy); } main() { scanf("%lld",&T); while(T--) { scanf("%lld%lld%lld",&n,&h,&r); for(int i=1;i<=n;i++) { scanf("%lld%lld%lld",&a,&b,&c); s[i].x=a; s[i].y=b; s[i].z=c; par[i]=i; } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j) continue; if(dis(s[i].x,s[i].y,s[i].z, s[j].x,s[j].y,s[j].z)<=2*r) merge(i,j); } } for(int i=1;i<=n;i++) { if(s[i].z-r<=0) { for(int j=1;j<=n;j++) { if(s[j].z+r>=h) { if(find(i)==find(j)) { printf("Yes "); flag=1; break; } } } if(flag==1) break; } } if(flag==0) printf("No "); flag=0; } return 0; }