1. 程式人生 > >UVA12171-Sculpture(離散化+floodfill)

UVA12171-Sculpture(離散化+floodfill)

con muc desc sep truct empty time quit side

Problem UVA12171-Sculpture

Accept: 196 Submit: 1152

Time Limit: 3000 mSec

技術分享圖片 Problem Description

Imagine a box, made of copper plate. Imagine a second one, intersecting the rst one, and several others, intersecting each other (or not). That is how the sculptor Oto Boxing constructs his sculptures. In fact he does not construct that much, he only makes the design; the actual construction is contracted out to a construction company. For the calculation of the costs of construction the company needs to know the total area of copper plate involved. Parts of a box that are hidden in another box are not realized in copper, of course. (Copper is quite expensive, and prices are rising.) After construction, the total construction is plunged into a bath of chemicals. To prevent this bath from running over, the construction company wants to know the total volume of the construction. Given that a construction is a collection of boxes, you are asked to calculate the area and the volume of the construction. Some of Oto’s designs are connected, others are not. Either way, we want to know the total area and the total volume. It might happen that the boxes completely enclose space that is not included in any of the boxes (see the second example below). Because the liquid cannot enter that space, its volume must be added to the total volume. Copper plate bordering this space is super?uous, of course, so it does not add to the area.

技術分享圖片 Input

On the rst line one positive number: the number of testcases, at most 100. After that per testcase:

? One line with an integer n (1 ≤ n ≤ 50): the number of boxes involved.

? n lines with six positive integers x0,y0,z0,x ,y,z (1 ≤ x0,y0,z0,x,y,z ≤ 500): the triple (x0,y0,z0) is the vertex of the box with the minimum values for the coordinates and the numbers x, y, z are the dimensions of the box (x, y and z dimension, respectively). All dimensions are in centimeters. The sides of the boxes are always parallel to the coordinate axes.

技術分享圖片 Output

Per testcase: ? One line with two numbers separated by single spaces: the total amount of copper plate needed (in cm2), and the total volume (in cm3).

技術分享圖片 Sample Input

2
2
1 2 3 3 4 5
6 2 3 3 4 5
7
1 1 1 5 5 1
1 1 10 5 5 1
1 1 2 1 4 8
2 1 2 4 1 8
5 2 2 1 4 8
1 5 2 4 1 8
3 3 4 1 1 1

技術分享圖片 Sample Output

188 120

250 250

題解:這個題還是挺費勁的,floodfill倒不是重點,困難的地方在於離散化(起碼對我來說很困難),原來也做過兩道離散化的題,但是對於這個東西沒啥概念,這道題讓我對離散化的理解深刻了一些。

離散化之後這裏的長方體就變成了正方體,想到這一點對於理解整個思路很有幫助。

這裏面還有一個思想就是用點代表長方體,此處用的是三個坐標均為最小的點來代表一個長方體。

lrj的代碼中把函數封裝在結構體感覺灰常方便,學習了。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <queue>
  6 #include <algorithm>
  7 using namespace std;
  8 
  9 const int maxn = 50+5;
 10 const int maxl = 1000+1;
 11 
 12 int xl[maxn],yl[maxn],zl[maxn];
 13 int xr[maxn],yr[maxn],zr[maxn];
 14 
 15 int gra[maxn<<1][maxn<<1][maxn<<1];
 16 int xx[maxn<<1],yy[maxn<<1],zz[maxn<<1];
 17 int xcnt,ycnt,zcnt;
 18 
 19 int dx[6] = {1,-1,0,0,0,0};
 20 int dy[6] = {0,0,1,-1,0,0};
 21 int dz[6] = {0,0,0,0,1,-1};
 22 
 23 struct Point{
 24     int x,y,z;
 25     Point(int x = 0,int y = 0,int z = 0) :
 26         x(x),y(y),z(z) {}
 27     bool valid()const{
 28         if(0<=x && 0<=y && 0<=z && x<xcnt-1 && y<ycnt-1 && z<zcnt-1) return true;
 29         else return false;
 30     }
 31     bool solid()const{
 32         return gra[x][y][z] == 1;
 33     }
 34     void Setvis()const{
 35         gra[x][y][z] = 2;
 36     }
 37     bool Getvis()const{
 38         return gra[x][y][z] ==2;
 39     }
 40     Point neighbour(int i)const{
 41         return Point(x+dx[i],y+dy[i],z+dz[i]);
 42     }
 43     int volume()const{
 44         return (xx[x+1]-xx[x])*(yy[y+1]-yy[y])*(zz[z+1]-zz[z]);
 45     }
 46     int area(int dir)const{
 47         if(dx[dir] != 0) return (yy[y+1]-yy[y])*(zz[z+1]-zz[z]);
 48         else if(dy[dir] != 0) return (xx[x+1]-xx[x])*(zz[z+1]-zz[z]);
 49         else return (xx[x+1]-xx[x])*(yy[y+1]-yy[y]);
 50     }
 51 };
 52 
 53 int ID_find(int *num,int len,int tar){
 54     return lower_bound(num,num+len,tar)-num;
 55 }
 56 
 57 void floodfill(int &V,int &S){
 58     Point c;
 59     c.Setvis();
 60     queue<Point> que;
 61     que.push(c);
 62     while(!que.empty()){
 63         Point first = que.front();
 64         que.pop();
 65         V += first.volume();
 66         for(int i = 0;i < 6;i++){
 67             Point Next = first.neighbour(i);
 68             if(Next.valid()){
 69                 if(Next.solid()){
 70                     S += first.area(i);
 71                 }
 72                 else if(!Next.Getvis()){
 73                     Next.Setvis();
 74                     que.push(Next);
 75                 }
 76             }
 77         }
 78     }
 79     V = maxl*maxl*maxl-V;
 80 }
 81 
 82 void Unique(int *num,int cnt,int &ccnt){
 83     sort(num,num+cnt);
 84     ccnt = unique(num,num+cnt)-num;
 85 }
 86 
 87 int main()
 88 {
 89     //freopen("input.txt","r",stdin);
 90     int iCase;
 91     scanf("%d",&iCase);
 92     while(iCase--){
 93         int n;
 94         scanf("%d",&n);
 95         int cnt = 2;
 96         xx[0] = yy[0] = zz[0] = 0;
 97         xx[1] = yy[1] = zz[1] = maxl;
 98         for(int i = 0;i < n;i++){
 99             scanf("%d%d%d%d%d%d",&xl[i],&yl[i],&zl[i],&xr[i],&yr[i],&zr[i]);
100             xr[i] += xl[i],yr[i] += yl[i],zr[i] += zl[i];
101             xx[cnt] = xl[i],yy[cnt] = yl[i],zz[cnt++] = zl[i];
102             xx[cnt] = xr[i],yy[cnt] = yr[i],zz[cnt++] = zr[i];
103         }
104         Unique(xx,cnt,xcnt);
105         Unique(yy,cnt,ycnt);
106         Unique(zz,cnt,zcnt);
107         memset(gra,0,sizeof(gra));
108         for(int i = 0;i < n;i++){
109             int X1 = ID_find(xx,xcnt,xl[i]),X2 = ID_find(xx,xcnt,xr[i]);
110             int Y1 = ID_find(yy,ycnt,yl[i]),Y2 = ID_find(yy,ycnt,yr[i]);
111             int Z1 = ID_find(zz,zcnt,zl[i]),Z2 = ID_find(zz,zcnt,zr[i]);
112             for(int X = X1;X < X2;X++){            //這裏一定是 < ,因為是以點代體,如果點到了邊界,體就出去了
113                 for(int Y = Y1;Y < Y2;Y++){
114                     for(int Z = Z1;Z < Z2;Z++){
115                         gra[X][Y][Z] = 1;
116                     }
117                 }
118             }
119         }
120         int V = 0,S = 0;
121         floodfill(V,S);
122         printf("%d %d\n",S,V);
123     }
124     return 0;
125 }

UVA12171-Sculpture(離散化+floodfill)