BZOJ 3234: [Ahoi2013]立方体

BZOJ 3234: [Ahoi2013]立方体

标签(空格分隔): OI-BZOJ OI-计算几何


Time Limit: 10 Sec
Memory Limit: 64 MB


Description

在一个三维空间中有N个立方体,第i个立方体占据x_i1,y_i1, z_i1 --- x_i2, y_i2, z_i2的位置。这N个立方体可能有相交,也可能重叠。这N个立方体构成一个大的几何图形。现在求这个几何图形的外表面积

Input

第一行,一个整数N,表示立方体的个数。
第二行至第N+1行,每行6个用空格隔开的整数,分别表示x1,y1,z1,x2,y2,z2.
Output

一行,一个整数,表示外表面积的大小。

Sample Input

input 1

1

0 0 0 1 1 1

input 2

2

0 1 0 3 2 1

1 0 0 2 3 1

Sample Output

output 1

6

output 2

22
HINT

对于第一个样例

此处输入图片的描述

对于第二个样例

此处输入图片的描述

1<=N<=200,0<=x_i1,y_i1,z_i1,x_i2,y_i2,z_i2<=200,x_i1<x_i2,y_i1<y_i2,z _i1<z_i2

Source

鸣谢zhonghaoxi提供数据,原数据似有误


Solution

开始的时候稍微纠结了一下空心内部空间的面积算不算。。并不算,都说了是外表面积。
开始想到的是扫描线,直接开个200*200的数组暴力修改,加到1或减到0就记录答案\(O(n^3)\)
后来想了想统计表面积的时候可以bfs外面的空间的小立方体,如果进入被
覆盖的小立方体就记录答案,每块外表面的2边一定是:一个被覆盖的小立方
体和未被覆盖的小立方体。
至于判断是否被覆盖,只要在立方体8个顶点打+-标记,做前缀和。
具体来说,在(x1,y1,z1)标记+1则{(x,y,z)|x>=x1&&y>=y1&&z>=x1}被覆盖
在(x1,y1,z2)标记-1则{(x,y,z)|x>=x1&&y>=y1&&z>=z1}被删除
容斥即可


Code

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#include<vector>
using namespace std;
#define PA pair<int,int>
int read()
{
    int s=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
    return s*f;
}
//smile please
int n,f[205][205][205],ans,mx,my,mz;
bool vis[205][205][205];
int dx[6]={-1,1,0,0,0,0},dy[6]={0,0,-1,1,0,0},dz[6]={0,0,0,0,-1,1};
struct pai;
queue<pai>q;int kk;
struct pai
{
    int x,y,z;
    void dfs()
       {
        if(vis[x][y][z])return;
        if(f[x][y][z])ans++;
        else
           {vis[x][y][z]=1;
            for(int i=0;i<6;i++)
                q.push((pai){x+dx[i],y+dy[i],z+dz[i]});
           }
        kk++;
       }
};
int main()
{
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    int x1,x2,y1,y2,z1,z2;
    n=read();
    for(int i=1;i<=n;i++)
       {x1=read()+2,y1=read()+2,z1=read()+2,
        x2=read()+2,y2=read()+2,z2=read()+2;
        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]--;
        mx=max(mx,x2);
        my=max(my,y2);
        mz=max(mz,z2);
       }
    for(int i=1;i<=mx+1;i++)
        for(int j=1;j<=my+1;j++)
            for(int k=1;k<=mz+1;k++)
                f[i][j][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]-f[i-1][j][k-1]-f[i][j-1][k-1]+f[i-1][j-1][k-1];
    for(int i=0;i<=mx+2;i++)
        for(int j=0;j<=my+2;j++)
            for(int k=0;k<=mz+2;k++)
                if(i==0||j==0||k==0||i==mx+2||j==my+2||k==mz+2)
                  vis[i][j][k]=1;
    for(q.push((pai){1,1,1});!q.empty();)
       {pai x=q.front();q.pop();
        x.dfs();
       }
    printf("%d\n",ans);
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}

posted on 2016-03-12 21:23  wuyuhan  阅读(...)  评论(...编辑  收藏

导航