当我这样一个蒟蒻看到题解区里都是类似并查集、dfs、bfs 这种高深的东西时,真的很难受(因为看不懂

于是我整了一个小时,终于整出一个人畜无害老少皆宜即使是蒟蒻也能看懂的代码了

以上是废话

思路

简单来说,先按高矮(即 z)从小到大排序,如果一个洞能和它前面任何一个洞相连或是直接与下表面相连,就存进一个数组,如果数组中有哪个能和上表面相连,就输出 Yes,反之,输出 No。

因为事先已经排过了序,所以可以保证数组中的数都是与下表面相连的,就像 a1 与下底面相连,a2 与 a1 相连,所以 a2 也是和下底面相连的,所以不用管它和哪个相连,知道是连着的就对了

附上喜闻乐见的 AC 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
struct qwq//结构体定义数组
{
ll x;
ll y;
ll z;
};
bool cmp(qwq a,qwq b)//自定义结构体 sort 排序
{
if(a.z!=b.z) return a.z<b.z;//一定记得以高矮优先
if(a.x!=b.x) return a.x<b.x;
if(a.y!=b.y) return a.y<b.y;
}
ll dist(ll x1,ll y1,ll z1,ll x2,ll y2,ll z2)
{
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2);
}
ll t,n,h,r,s,flag;
qwq tree[1010],g[1010];
int main()
{
scanf("%lld",&t);
for(int c=1;c<=t;c++)
{
scanf("%lld%lld%lld",&n,&h,&r);
s=0;
flag=0;
memset(tree,0,sizeof(tree));//以上是初始化
for(int i=1;i<=n;i++)
scanf("%lld%lld%lld",&g[i].x,&g[i].y,&g[i].z);
sort(g+1,g+1+n,cmp);//排序
for(int i=1;i<=n;i++)
{
flag=0;
if(g[i].z-r<=0)//如果与下底面相连就直接存入数组
{
s++;
tree[s].x=g[i].x;
tree[s].y=g[i].y;
tree[s].z=g[i].z;
}
for(int j=1;j<=s;j++)
if(dist(g[i].x,g[i].y,g[i].z,tree[j].x,tree[j].y,tree[j].z)<=4*r*r)//判断是否相切或相交
{
s++;
tree[s].x=g[i].x;
tree[s].y=g[i].y;
tree[s].z=g[i].z;
break;//只要有一个与其相连,就退出循环
}
if(tree[s].z+r>=h)//判断是否与上顶面相连
{
flag=1;
break;
}
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}

如果哪里做的不对,请各位大佬帮忙指出,十分感谢