题解【洛谷P3958】[NOIP2017]奶酪

题面

题解

我们考虑使用一个并查集维护空洞之间的关系。

如果两个空洞能相互到达,那么它们的祖先也是相同的。

枚举从哪一个空洞开始,能否到达奶酪的上表面。

如果能到达就输出Yes,否则输出No

注意开long long

代码

#include <bits/stdc++.h>
#define itn int
#define int long long
#define gI gi

using namespace std;

inline int gi()
{
    int f = 1, x = 0; char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return f * x;
}

const int maxn = 1003;

bool fl = false;
int t, n, m, h, r, fa[maxn], x[maxn], y[maxn], z[maxn];

inline bool getdis(int x, int y, int z)
{
    if (x * x + y * y + z * z <= 4 * r * r) return true;//计算能否互相到达
    return false;
}

inline void kz(int u)//进行扩展
{
    if (!fl) return;//已经有解了就直接返回
    if (z[u] + r >= h)//到达了上表面
    {
        fl = false;
        return;
    }
    for (int i = 1; i <= n; i+=1)
    {
        if (fa[i] == 1) continue;//能够互相到达就不要再计算了
        if (getdis(x[i] - x[u], y[i] - y[u], z[i] - z[u]))//可以从u到i
        {
            fa[i] = 1;//记录祖先
            kz(i);//扩展i
        }
    }
}

inline void solve()
{
    for (int i = 1; i <= n; i+=1)
    {
        if (z[i] <= r)//可以从下表面开始
        {
            fa[i] = 1;//记录祖先
            kz(i);//进行扩展
        }
    }
}

signed main()
{
    t = gi();
    while (t--)
    {
        n = gi(), h = gi(), r = gi();
        for (int i = 1; i <= n; i+=1) fa[i] = 0;//初始化
        for (int i = 1; i <= n; i+=1)
        {
            x[i] = gi(), y[i] = gi(), z[i] = gi();
        }
        fl = true;
        solve();
        if (fl) puts("No");
        else puts("Yes");//输出
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xsl19/p/11821235.html