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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章