P3958 奶酪
题解
先对球按照高度(即 z z z坐标)排个序,对于每个球,我们对与它相交或者相切的球建边,然后从最下面的球开始 b f s bfs bfs就好了。(坑点:有可能与下表面相交或相切的不止一个,还有距离要用double…)
代码
#include<bits/stdc++.h>
using namespace std;
struct ball{
int x,y,z;
bool operator < (const ball & u) const {
return z < u.z;
}
}a[1010];
int n,h,r,T,e[1010][1010];
bool vis[1010][1010];
double dist(ball p1,ball p2)
{
return sqrt(1LL*(p1.x-p2.x)*(p1.x-p2.x)+1LL*(p1.y-p2.y)*(p1.y-p2.y)+1LL*(p1.z-p2.z)*(p1.z-p2.z));
}
bool love(ball p,ball q)
{
return dist(p,q) - r*2 <= 0;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
memset(vis,0,sizeof vis);
scanf("%d%d%d",&n,&h,&r);
for(int i = 0; i < n; ++i){
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
}
for(int i = 0; i < n; ++i){
for(int j = 0; j < n; ++j){
if(i==j) e[i][j] = 1;
else e[i][j] = (1<<30);
}
}
sort(a,a+n);
for(int i = 0; i < n; ++i){
for(int j = i+1; j < n; ++j){
if(love(a[i],a[j])){
e[i][j] = 1;
//printf("%d %d\n",i,j);
e[j][i] = 1;
}
}
}
bool f = 0;
queue<int> pq;
for(int i = 0; i < n; ++i){
if(a[i].z - r <= 0){
pq.push(i);
// printf("i = %d z = %d r = %d\n",i,a[i].z,r);
}
}
while(!pq.empty()){
int cur = pq.front();
pq.pop();
if((a[cur].z + r) >= h) {
f = 1;
// printf("%d %d %d\n",a[cur].x,a[cur].y,a[cur].z);
break;
}
for(int i = 0; i < n; ++i){
if(!vis[cur][i]&&e[cur][i]==1){
vis[cur][i] = 1;
pq.push(i);
}
}
}
if(a[0].z - r > 0) f = 0;
puts(f?"Yes":"No");
}
return 0;
}