Description
现有一块大奶酪,它的高度为 hh,它的长度和宽度我们可以认为是无限大的,奶酪 中间有许多 半径相同 的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中, 奶酪的下表面为z = 0z=0,奶酪的上表面为z = hz=h。
现在,奶酪的下表面有一只小老鼠 Jerry,它知道奶酪中所有空洞的球心所在的坐 标。如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别 地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果 一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。
位于奶酪下表面的 Jerry 想知道,在 不破坏奶酪 的情况下,能否利用已有的空洞跑 到奶酪的上表面去?
Solution
可以相连的空洞间连边,BFS判断相通即可。
Code
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
typedef long long LL;
#define For(i, j, k) for (int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
const int maxn = 1003, maxm = 1000003;
struct DCR
{
LL x, y, z;
bool operator < (const DCR &dcr) const { return z < dcr.z; }
}a[maxn];
LL r, h;
int n, beg[maxn], nex[maxm], v[maxm], e, T;
bool vis[maxn], isend[maxn];
queue<int> q;
inline void add(int uu, int vv) { v[++ e] = vv; nex[e] = beg[uu]; beg[uu] = e; }
LL dist(DCR A, DCR B) { return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y) + (A.z - B.z) * (A.z - B.z); }
inline void Init()
{
cin >>n >> h >> r;
// scanf("%d%lld%lld", &n, &h, &r);
For(i, 1, n) cin >>a[i].x >>a[i].y >> a[i].z;//scanf("%lld%lld%lld\n", &a[i].x, &a[i].y, &a[i].z);
sort(a + 1, a + 1 + n);
e = 0; Set(beg, 0);
For(i, 1, n - 1)
For(j, i + 1, n)
{
if (a[j].z - a[i].z > 2 * r) break;
if (dist(a[i], a[j]) <= 4 * r * r) add(i, j), add(j, i);
}
}
inline bool BFS()
{
Set(vis, 0); Set(isend, 0);
while (!q.empty()) q.pop();
For(i, 1, n) if (a[i].z <= r) { q.push(i); vis[i] = 1; if (h-a[i].z <=r) return 1; } else break;
Fordown(i, n, 1) if (h - a[i].z <= r) isend[i] = 1; else break;
while (!q.empty())
{
int u = q.front(); q.pop();
for (int i = beg[u]; i; i = nex[i]) if (!vis[v[i]])
{
vis[v[i]] = 1;
if (isend[v[i]]) return 1;
q.push(v[i]);
}
}
return 0;
}
int main()
{
scanf("%d", &T);
while (T --) {
Init();
if (BFS()) puts("Yes"); else puts("No");
}
return 0;
}
//云开远见汉阳城,犹是孤帆一日程。
//估客昼眠知浪静,舟人夜语觉潮生。
//三湘愁鬓逢秋色,万里归心对月明。
//旧业已随征战尽,更堪江上鼓鼙声。
//--卢纶《晚次鄂州》