【题目来源】
【分析】
看数据规模,T<=20,n<=1e3,则每次询问可以承受O(n^2)。
采用广度优先搜索,把从底部能进入的洞加入队列,并标记vis=1(可到达),然后开始搜索,每个与队列中连通的洞可以加入队列(条件:洞心距离<=2*r),并标记其vis=1。最后判断是否存在这样的洞:(1)能到达顶部(2)vis=1。
特别注意爆int,int数据做运算,每一部分都要强制转换成long long型:
ll dist(POI a,POI b){
return (ll)(a.x-b.x)*(a.x-b.x)+(ll)(a.y-b.y)*(a.y-b.y)+(ll)(a.z-b.z)*(a.z-b.z);
}
以及注意下面也要转换成long long型:
if(dist(p[u],p[i])<=(ll)4*r*r){
vis[i]=1;
q.push(i);
}
#广度优先搜索(BFS)
【代码】
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
using namespace std;
const int N=1e3+5;
const int T=20;
struct POI{
int x,y,z;
}p[N];
int vis[N];
int t;
int n,h,r;
ll dist(POI a,POI b){
return (ll)(a.x-b.x)*(a.x-b.x)+(ll)(a.y-b.y)*(a.y-b.y)+(ll)(a.z-b.z)*(a.z-b.z);
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&h,&r);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
}
//---初始化--
for(int i=1;i<=n;i++){
vis[i]=0;
}
//-----------
queue<int>q;
for(int i=1;i<=n;i++){
if(p[i].z-r<=0){
vis[i]=1;
q.push(i);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=1;i<=n;i++){
if(i==u || vis[i]==1)continue;
if(dist(p[u],p[i])<=(ll)4*r*r){
vis[i]=1;
q.push(i);
}
}
}
int f=0;
for(int i=1;i<=n;i++){
if(p[i].z+r>=h && vis[i]==1){
f=1;
break;
}
}
if(f==1)puts("Yes");
else puts("No");
}
return 0;
}