【正经题解】奶酪
2024-02-22 11:49:37
发布于:浙江
17阅读
0回复
0点赞
暴力思路:
.先把所有能够到达奶酪底部的点都加入队列
.每次从队列中弹出一个,判断他的 坐标加上 后是否能到达顶部,可以的话直接退出循环
.否则判断它和所有的点是否能够连通,如果可以连通就加入队列
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define ll long long
#define rint register int
using namespace std;
const int maxn=1005;
ll T,n,h,r,d;
ll x[maxn],y[maxn],z[maxn];
bool vis[maxn],ok;
inline ll read(){//快读,没加符号的我死了一次
char c=getchar();
ll s=0,st=1;
while (c<'0'||c>'9') {
if (c=='-') st=-1;
c=getchar();
}
while (c>='0'&&c<='9') {
s=(s<<3)+(s<<1)+c-'0';
c=getchar();
}
return s*st;
}
ll ab(ll x){return x>0?x:-x;}//绝对值
ll sq(ll x){return x*x;}//平方
int main(){
T=read();
while (T--){
n=read();h=read();r=read();
d=r*2;
for (rint i=1;i<=n;++i){
x[i]=read();
y[i]=read();
z[i]=read();
}
queue <int> q;
for (rint i=1;i<=n;++i){
if (z[i]+r>=0&&z[i]-r<=0) {
vis[i]=1;
q.push(i);
}
}
ll dis,dx,dy,dz;
while (!q.empty()){
int k=q.front();q.pop();
if (r+z[k]>=h) {//如果已经到达了顶端就退出
ok=1;break;
}
for (rint i=1;i<=n;++i){
if (vis[i]) continue;//访问过的点不再访问
dx=ab(x[k]-x[i]);
if (dx>d) continue;
//可以省去很多不必要的计算,毕竟只有一个坐标相减就已经超过了直径,下同
dy=ab(y[k]-y[i]);
if (dy>d) continue;
dz=ab(z[k]-z[i]);
if (dz>d) continue;
dis=sq(dx)+sq(dy)+sq(dz);
if (dis<=sq(d)) {
vis[i]=1;
q.push(i);
}
}
}
if (ok) printf("Yes\n"),ok=0;
else printf("No\n");
for (rint i=1;i<=n;++i) vis[i]=0;//手动清零
}
return 0;
}
这里空空如也
有帮助,赞一个