zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    	//fclose(stdin);
    	//fclose(stdout);
    	return 0;
    }
    
    
  • 相关阅读:
    C# 小规模查找集合性能测试
    高级前端开发不可或缺的知识
    移动前端开发-单页应用(spa)模型
    移动开发之用视频做背景
    纯CSS打造忙碌光标
    移动前端开发之数据库操作篇
    如何从源码中学习javascript
    Deffered.js的实现原理
    Codeforces Round #381 (Div. 2)
    2017 ZSTU寒假排位赛 #6
  • 原文地址:https://www.cnblogs.com/wuyuhan/p/5270112.html
Copyright © 2011-2022 走看看