bzoj3234: [Ahoi2013]立方体 括号法

本文介绍了一种利用括号法简化复杂几何问题的解决思路,通过处理8个角并应用前缀和,有效地识别出了几何结构中的面。详细步骤包括定义变量、结构体、方向数组以及实现BFS算法来遍历并计数面。

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

看到题目首先想到200^4的乱搞。竟然有70分。。。。

正解是神奇的括号法,对8个角进行处理,然后求一下前缀和。

再从一个没被包住的点开始访问,如果访问到一个点的f值是正数,说明这是一个面。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int f[210][210][210];
bool vis[210][210][210];
int n;
struct node
{
    int x,y,z;
};
int dx[]={1,-1,0,0,0,0};
int dy[]={0,0,1,-1,0,0};
int dz[]={0,0,0,0,1,-1};
int maxx,maxy,maxz,ans;
int minx=222,miny=222,minz=222;
bool judge(int x,int y,int z)
{
    if(x>=minx-1&&x<=maxx&&y>=miny-1&&y<=maxy&&z>=minz-1&&z<=maxz)
        return true;
    return false;
}
void bfs(int x,int y,int z)
{
    node now,next;
    int xx,yy,zz;
    now.x=x;
    now.y=y;
    now.z=z;
    vis[x][y][z]=1;
    queue<node>q;
    q.push(now);
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        for(int i=0;i<6;i++)
        {
            xx=now.x+dx[i];
            yy=now.y+dy[i];
            zz=now.z+dz[i];
            if(!judge(xx,yy,zz)) continue;
            if(vis[xx][yy][zz]) continue;
            if(f[xx][yy][zz]) ans++;
            else
            {
                vis[xx][yy][zz]=1;
                next.x=xx;
                next.y=yy;
                next.z=zz;
                q.push(next);
            }
        }
    }
}
int main()
{
    scanf("%d",&n);
    int x1,x2,y1,y2,z1,z2;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
        x1++;y1++;z1++;
        x2++;y2++;z2++;
        f[x1][y1][z1]++;
        f[x1][y1][z2]--;
        f[x1][y2][z1]--;
        f[x2][y1][z1]--;
        f[x2][y2][z1]++;
        f[x2][y1][z2]++;
        f[x1][y2][z2]++;
        f[x2][y2][z2]--;

        minx=min(minx,x1);
        miny=min(miny,y1);
        minz=min(minz,z1);

        maxx=max(maxx,x2+2);
        maxy=max(maxz,y2+2);
        maxz=max(maxz,z2+2);
    }
    for(int i=minx;i<=maxx;i++)
    {
        for(int j=miny;j<=maxy;j++)
        {
            for(int k=minz;k<=maxz;k++)
            {
                f[i][j][k]+=f[i-1][j][k]+f[i][j-1][k]+f[i][j][k-1]+f[i-1][j-1][k-1];
                f[i][j][k]-=f[i-1][j-1][k]+f[i][j-1][k-1]+f[i-1][j][k-1];
            }
        }
    }
    bfs(minx,miny,minz);
    printf("%d\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值