hiho1291(逆序思维,并查集)

题目链接:【https://hihocoder.com/problemset/problem/1291】

题意:在《我的世界》游戏中放置沙盒,沙盒为体积为1的正方体,按顺序给你一些坐标,然后问你按上面的顺序在这些坐标上放置沙盒是否合法:判断合法的条件a:沙盒必须放置在地面上或者与另外的沙盒共面(只要共面就可以).b:必须从外部放入某个坐标,也就说要放置的坐标不能被沙盒包围,也不能从地面下放进去PS:(题中说的是极远点可以不经过沙盒和地面到达要放置的点)。

For 20% of the data, 1 <= N <= 1000, 1 <= x, y, z <= 10.

For 100% of the data, 1 <= N <= 100000, 1 <= x, y, z <= 100.

题解:我们先不管条件b,只看条件a,然后判断是否合法。放置完以后我们在再从最后一个点删除,具体做法是:(坐标都在 1 <= x, y, z <= 100.)放置完沙盒以后,我们在100*100*100这个立方体外边在建立一层空座标把上,左右,前后全部覆盖。表示没有被放沙盒,然后我们把所有的空坐标连接在一起放入并查集,然后我们从最后一个点开始删点,删去的点的坐标与上下左右前后(如果下不为地的话)的空左边建立联系放入并查集,然后判断这个删除的坐标与我们在表层建立的左边是不是有联系即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 150;
int dir[6][3] = {0, 0, 1, 0, 0, -1, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0};
int E[maxn][maxn][maxn];
int X[105 * 105 * 105], Y[105 * 105 * 105], Z[105 * 105 * 105];
int F[115 * 115 * 115];
int Find(int u)
{
    if(u == F[u]) return F[u];
    else return F[u] = Find(F[u]);
}
void adde(int u, int v)
{
    int x = Find(u);
    int y = Find(v);
    if(x != y) F[x] = y;
}
int main ()
{
    int T, n;
    scanf("%d", &T);
    while(T--)
    {
        memset(E, 0, sizeof(E));
        bool fg = 1;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d%d", &X[i], &Y[i], &Z[i]);
            if(!fg) continue;
            if(E[X[i]][Y[i]][Z[i]]) fg = 0;//重复放木块
            E[X[i]][Y[i]][Z[i]] = 1;
            if(Z[i] == 1) continue;//放在地上
            int d = 0;
            for(d = 0; d < 6; d++)
            {
                int x = X[i] + dir[d][0];
                int y = Y[i] + dir[d][1];
                int z = Z[i] + dir[d][2];
                if(E[x][y][z]) break;
            }
            if(d == 6) fg = 0;
        }
        if(!fg)
        {
            printf("No\n");
            continue;
        }

        for(int i = 1; i <= 101 * 102 * 102 + 101 * 102 + 101; i++)
            F[i] = i;
        for(int i = 0; i <= 101; i++)//横坐标
            for(int j = 0; j <= 101; j++)//纵坐标
                for(int k = 1; k <= 101; k++)//竖坐标
                {
                    if(!E[i][j][k])
                        for(int d = 0; d < 6; d++)
                        {
                            int x = i + dir[d][0];
                            int y = j + dir[d][1];
                            int z = k + dir[d][2];
                            if(x >= 0 && x <= 101 && y >= 0 && y <= 101 && z >= 1 && z <= 101 && !E[x][y][z])
                                adde(i * 102 * 102 + j * 102 + k, x * 102 * 102 + y * 102 + z);
                        }
                }
        for(int i = n; i >= 1; i--)
        {
            E[X[i]][Y[i]][Z[i]] = 0;
            for(int d = 0; d < 6; d++)
            {
                int x = X[i] + dir[d][0];
                int y = Y[i] + dir[d][1];
                int z = Z[i] + dir[d][2];
                if(x >= 0 && x <= 101 && y >= 0 && y <= 101 && z >= 1 && z <= 101 && !E[x][y][z])
                    adde(X[i] * 102 * 102 + Y[i] * 102 + Z[i], x * 102 * 102 + y * 102 + z);
            }
            int x = Find(X[i] * 102 * 102 + Y[i] * 102 + Z[i]);
            int y = Find(101 * 102 * 102 + 101 * 102 + 101);
            if(x != y)
            {
                fg = 0;
                break;
            }
        }
        if(fg) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

 

posted @ 2017-04-01 10:58  _Mickey  阅读(254)  评论(0编辑  收藏  举报