UVA12171

题目大意:

给你一些长方体的坐标,算他们的体积(包括被围起来的体积),面积就是外表面的面积。就想象成将这些长方体放进水里,在水占的体积和水接触的表面积。

分析:

最原始的想法就是按坐标bfs,可以找出体积和表面积,但这一题的数组却开不下 500*500*500已经超过一亿了,办法就是离散化。

怎么离散化呢?因为只有50个长方体,所以最多有100个坐标 100*100*100 100万可以接受。那么按照常规的思路,从坐标原点开始bfs,一个方块一个方块的搜索,并且计算体积和面积,离散化的时候把每个点的原坐标记下来方便计算,此外在程序的书写上推荐把函数写成结构体的成员函数,在bfs时计算和判断都会相对来说比较简单。

#include<bits/stdc++.h>
using namespace std;
const int maxc=1005;
const int maxn=105;
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 color[maxn][maxn][maxn];
int xs[maxn],ys[maxn],zs[maxn];
int X[maxn],Y[maxn],Z[maxn],X0[maxn],Y0[maxn],Z0[maxn];
int t,n,nx,ny,nz;
struct Cell
{
    int x,y,z;
    Cell(int x,int y,int z):x(x),y(y),z(z) {}
    void Setvis()//外围方块
    {
        color[x][y][z]=2;
     } 
     bool getvis()
     {
     	return color[x][y][z]==2;
     }
     bool solid()//想象成固体方块
     {
     	return color[x][y][z]==1;
     }
     int volume()//离散化后每个单位长方体的体积
     {
     	return (xs[x+1]-xs[x])*(ys[y+1]-ys[y])*(zs[z+1]-zs[z]);
     }
     int area(int i)//根据移动的方向计算面积
     {
     	if(dx[i]!=0) return (ys[y+1]-ys[y])*(zs[z+1]-zs[z]);
     	if(dy[i]!=0) return (xs[x+1]-xs[x])*(zs[z+1]-zs[z]);
     	if(dz[i]!=0) return (xs[x+1]-xs[x])*(ys[y+1]-ys[y]);
     }
     bool valid()//不越界
     {
     	return x>=0&&x<nx-1&&y>=0&&y<ny-1&&z>=0&&z<nz-1;
     }
     Cell neighbour(int i)//行走函数
     {
        return Cell(x+dx[i],y+dy[i],z+dz[i]);
     }
};
int ID(int *x,int n,int k)//离散化后点的编号
{
    return lower_bound(x,x+n,k)-x;
}
void floodfill(int &s,int &v)//bfs
{
    Cell c(0,0,0);
    queue<Cell> Q;
    Q.push(c);
    c.Setvis();
    while(!Q.empty())
    {
      c=Q.front();
      Q.pop();
      v+=c.volume();
      //cout<<v<<endl;
      //cout<<c.x<<" "<<c.y<<" "<<c.z<<endl;
      for(int i=0;i<6;i++)
      {
        Cell c2=c.neighbour(i); 
        if(!c2.valid()) continue;
        if(c2.solid()) s+=c.area(i);
        else if(!c2.getvis())
        {
        	c2.Setvis();
        	Q.push(c2);
        }
      }	
    } 
    v=maxc*maxc*maxc-v;//v计算的是外围水的体积
}
void discretization(int *x,int &n)//计算离散化后点的个数
{
        sort(x,x+n);
        n=unique(x,x+n)-x;
}
int main()
{
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&t);
        nx=ny=nz=2;
        xs[0]=ys[0]=zs[0]=0;
        xs[1]=ys[1]=zs[1]=maxc;
        for(int i=1;i<=t;i++)
        {
            scanf("%d%d%d%d%d%d",&X[i],&Y[i],&Z[i],&X0[i],&Y0[i],&Z0[i]);
            X0[i]+=X[i];Y0[i]+=Y[i];Z0[i]+=Z[i];
            xs[nx++]=X[i];xs[nx++]=X0[i];
            ys[ny++]=Y[i];ys[ny++]=Y0[i];
            zs[nz++]=Z[i];zs[nz++]=Z0[i];
        }
        discretization(xs,nx);
        discretization(ys,ny);
        discretization(zs,nz);
        memset(color,0,sizeof(color));
        
        for(int i=1;i<=t;i++)
        {
            int sx=ID(xs,nx,X[i]);int ex=ID(xs,nx,X0[i]);
            int sy=ID(ys,ny,Y[i]);int ey=ID(ys,ny,Y0[i]);
            int sz=ID(zs,nz,Z[i]);int ez=ID(zs,nz,Z0[i]);
            for(int X=sx;X<ex;X++)
            for(int Y=sy;Y<ey;Y++)
            for(int Z=sz;Z<ez;Z++)
                color[X][Y][Z]=1;
        }
        int s=0,v=0;
        floodfill(s,v);
        printf("%d %d\n",s,v);
        }
    return 0;
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值