zoj1063 Space Station Shielding

本文详细解析了一个关于三维立方体中防毒墙计算的问题,涉及到经典的floodfill算法的应用,以及如何通过广搜算法解决特殊条件下的扩散问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=63


 题目意思是:在一个N*M*K的三维立方体中,有些块是住着人的,而立方体外是有毒气体,现在必须给每个块的六面装上防毒墙,问需要多少面防毒强。当然连在一起的可以不装防毒强。这是一道经典的floodfill,但是这道题目有一个特别的地方是,如果没有住人的块,毒气通过外部会扩散来,但是没有住人的块,若六面都被住人的包围,就不会被扩散。


对外层的方块做标记,住人的方块若和外面相连则sum++。做标记时深搜会爆栈,用广搜。


#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <queue>
#include <time.h>
#include <list>
#include <stack>
using namespace std;
const double eps=1e-7;
const long long INF=(1<<30)-1;

#define N 500005
#define M 1000000000

typedef struct pp{int x,y,z;} point;

bool a[62][62][62],b[62][62][62],s[62][62][62];
int n,m,k,sum,c[70][70][70];

void zb(int num,int &x,int &y,int &z)
{
    z=num/(n*m);
    num%=(n*m);

    y=num/n;
    num%=n;

    x=num;

    x++;
    y++;
    z++;
}

void sur(point p1)
{
    stack<point> p;
    p.push(p1);

    point p2,p3;
    while (!p.empty())
    {
        p3=p.top();
        p.pop();
        int x,y,z;
        x=p3.x;
        y=p3.y;
        z=p3.z;

        if (x>0 && c[x-1][y][z]==0)
        {
            p2=p3;
            c[x-1][y][z]=2;
            p2.x=x-1;
            p.push(p2);
        }
        if (x<n+1 && c[x+1][y][z]==0)
        {
            p2=p3;
            c[x+1][y][z]=2;
            p2.x=x+1;
            p.push(p2);
        }
        if (y>0 && c[x][y-1][z]==0)
        {
            p2=p3;
            c[x][y-1][z]=2;
            p2.y=y-1;
            p.push(p2);
        }
        if (y<m+1 && c[x][y+1][z]==0)
        {
            p2=p3;
            c[x][y+1][z]=2;
            p2.y=y+1;
            p.push(p2);
        }
        if (z>0 && c[x][y][z-1]==0)
        {
            p2=p3;
            c[x][y][z-1]=2;
            p2.z=z-1;
            p.push(p2);
        }
        if (z<k+1 && c[x][y][z+1]==0)
        {
            p2=p3;
            c[x][y][z+1]=2;
            p2.z=z+1;
            p.push(p2);
        }
    }
}

void cou(int x,int y,int z)
{
    if (c[x-1][y][z]==2) sum++;
    if (c[x+1][y][z]==2) sum++;
    if (c[x][y-1][z]==2) sum++;
    if (c[x][y+1][z]==2) sum++;
    if (c[x][y][z-1]==2) sum++;
    if (c[x][y][z+1]==2) sum++;

}

int main()
{
    //freopen("a","r",stdin);

    int l,i,j,ii;

    while(1)
    {
        scanf("%d%d%d%d",&n,&m,&k,&l);
        if (n==0 && m==0 && k==0 && l==0) break;

        sum=0;

        memset(c,0,sizeof(c));
        int x,y,z;
        for (i=1;i<=l;i++)
        {
            scanf("%d",&j);
            zb(j,x,y,z);
            c[x][y][z]=1;
        }

        point p1;
        p1.x=p1.y=p1.z=0;
        sur(p1);

        for (i=1;i<=n;i++)
        for (j=1;j<=m;j++)
        for (ii=1;ii<=k;ii++)
        if (c[i][j][ii]==1) cou(i,j,ii);

        printf("The number of faces needing shielding is %d.\n",sum);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值