就这样一道水题我都要抄题解
一开始我用了一种比较玄学的算法:按纵坐标排序,然后按顺序查看它能不能由前面的点达到
但是后来发现可以被以下数据HACK:
我的玄学做法注定会先查看低处的洞,但是低处的洞可能是从高处的洞跑过来的
正解当然是搜索啦
我们让每一个与下表面相切的点向周围扩展,然后检查它们是否到达上表面
当然,不用回溯——被访问过而又回来了的点注定达不到上表面
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline void read(int &x)
{
x=0;register char c=getchar();int f=1;
for(; c<48||57<c; c=getchar()) if(c=='-')f=-1;
for(;48<=c&&c<=57;c=getchar()) x=x*10+(c&15);
x*=f;
}
inline void write(const int x)
{
if(x>9)write(x/10);
putchar(x%10|48);
}
struct point
{
int x,y,z;
friend bool operator <(const point &a,const point &b)
{return a.z<b.z;}
}a[1100];
int v[1100];
#define sqr(x) 1.0L*(x)*(x)//防爆long long
int n,h,r;
inline long double dist(point a,point b)
{return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)+sqr(a.z-b.z));}
bool dfs(int x)
{
if(a[x].z+r>=h)return 1;
for(int i=1;i<=n;i++)
if(!v[i]&&dist(a[i],a[x])<=2*r)
{
v[i]=1;
if(dfs(i))return 1;
}
return 0;
}
void Main()
{
memset(v,0,sizeof(v));
read(n),read(h),read(r);
for(int i=1;i<=n;i++)
read(a[i].x),read(a[i].y),read(a[i].z);
for(int i=1;i<=n;i++)
if(a[i].z<=r)
{
v[i]=1;
if(dfs(i))
{puts("Yes");return;}
}
puts("No");
}
int main()
{
int T;read(T);
while(T--)
Main();
return 0;
}