soj 1114. Food Cubes

题意:

在100*100*100的三维空间内,给出若干食物的坐标,如果一段空间被食物包围着,那么这段空间就成为一个洞,求洞的数目

思路:

对每一个不是食物的点做bfs的Flood Fill即可。(还有一种方法是对每一个是食物的点做dfs的Flood Fill,不过想想看如果是2,2,2到99,99,99是一个洞的话,这个洞的表面积,大约100*100*6 = 60000,爆栈吧,没尝试过)

代码:

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
#define N 105

int ix, ax, iy, ay, iz, az;
bool f[N][N][N];
struct P
{
    int x, y, z;
    P() {}
    P(int _x, int _y, int _z): x(_x), y(_y), z(_z) {}
    P operator + (const P &p) { return P(x+p.x, y+p.y, z+p.z); }
    bool legal() { return x>=ix&&x<=ax && y>=iy&&y<=ay && z>=iz&&z<=az; }
    bool hole() { return !f[x][y][z]; }
    void setF() { f[x][y][z] = true; }
};
P cur, nxt;
P d[6] = {P(1,0,0),P(-1,0,0),P(0,1,0),P(0,-1,0),P(0,0,1),P(0,0,-1)};
int ans;
void flood_fill(int x, int y, int z)
{
    f[x][y][z] = true;
    queue <P> Q;
    Q.push(P(x,y,z));
    bool flag = true;
    while (!Q.empty())
    {
        cur = Q.front();
        Q.pop();
        for (int i = 0; i < 6; ++ i)
        {
            nxt = cur + d[i];
            if (!nxt.legal()) flag = false;
            else if (nxt.hole())
            {
                nxt.setF();
                Q.push(nxt);
            }
        }
    }
    if (flag) ans ++;
}
void work()
{
    for (int i = ix; i <= ax; ++ i)
        for (int j = iy; j <= ay; ++ j)
            for (int k = iz; k <= az; ++ k)
                if (!f[i][j][k])
                    flood_fill(i,j,k);
}
int main()
{
    int t, n, x, y, z;
    scanf("%d", &t);
    while (t --)
    {
        memset(f, false, sizeof(f));
        ans = 0;
        ix = iy = iz = 100;
        ax = ay = az = 1;
        scanf("%d", &n);
        while (n --)
        {
            scanf("%d %d %d", &x, &y, &z);
            if (x > ax) ax = x; if (x < ix) ix = x;
            if (y > ay) ay = y; if (y < iy) iy = y;
            if (z > az) az = z; if (z < iz) iz = z;
            f[x][y][z] = true;
        }
        work();
        printf("%d\n", ans);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值