洛谷 P3958 奶酪

就这样一道水题我都要抄题解

一开始我用了一种比较玄学的算法:按纵坐标排序,然后按顺序查看它能不能由前面的点达到
但是后来发现可以被以下数据HACK:

我的玄学做法注定会先查看低处的洞,但是低处的洞可能是从高处的洞跑过来的
正解当然是搜索啦
我们让每一个与下表面相切的点向周围扩展,然后检查它们是否到达上表面
当然,不用回溯——被访问过而又回来了的点注定达不到上表面

#include
#include
#include
#include
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;
}

你可能感兴趣的:(做题笔记)