UVA12171-Sculpture(离散化+floodfill)

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 }

原文地址:https://www.cnblogs.com/npugen/p/9515205.html

时间: 2024-10-11 11:48:50

UVA12171-Sculpture(离散化+floodfill)的相关文章

UVa Sculpture(离散化 floodfill)

题意: 给定n个立方体的一个顶点坐标和3边长度,  问这些立方体组成的雕塑的表面积和体积,   坐标都是整数,n最大为50,  最大为500, 边长最大也是500. 分析: 继UVa221后又一道离散化 首先先深入理解一下离散化: (转自 http://www.cnblogs.com/jerryRey/p/4599388.html) 先来看一个问题:给你以下的网格,你需要多少空间去存储红点区间的信息呢? 只需要图上所示的1,2,3,4个点就足够表示红点所在区间了,为什么不是一个区间的第一个红点和

UVa 12171 (离散化 floodfill) Sculpture

题意: 三维空间中有n个长方体组成的雕塑,求表面积和体积. 分析: 我们可以在最外边加一圈“空气”,然后求空气的连通块的体积,最后用总体积减去即是雕塑的体积. 还有一个很“严重”的问题就是5003所占的空间太大,因此需要离散化.而在计算体积和表面积的时候要用原坐标. 离散化以后的坐标分别保存在xs.ys.zs,坐标为(x, y, z)的格子代表([xs[x], ys[y], zs[z]) ~ (xs[x+1], ys[y+1], zs[z+1]) 这一个小长方体. 这个题的难度对我来说属于大概思

hdu 2771(uva 12171) Sculpture bfs+离散化

题意: 给出一些边平行于坐标轴的长方体,这些长方体可能相交.也可能相互嵌套.这些长方体形成了一个雕塑,求这个雕塑的整体积和表面积. 题解: 最easy想到直接进行bfs或者dfs统计,但此题的麻烦之处在于求整个雕塑的外表面积和雕塑内部可能出现四个长方体所搭成的空心.空心不能计算到表面积中,可是计算整体积却要计入,于是直接bfs或者dfs不优点理.于是,能够想到直接统计整个雕塑外围的全部小方块.就可以非常方便地求出雕塑地表面积和体积(雕塑地整体积==整个空间地体积-外围想方块的体积),另一点就是因

UVa12171 hdu2771 UVaLive4291 Sculpture

填坑系列(p.171) orz rjl 代码基本和rjl的一样 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<iostream> 6 7 template<typename Q> Q read(Q& x) { 8 static char c, f; 9 for(f = 0; c = getc

uva12171 离散化

区间离散化,将1000*1000*1000缩小为最多100*100*100的空间,进行bfs; #include <cstdio> #include <string> #include <iostream> #include <cstring> #include <set> #include <cmath> #include <algorithm> #define LL long long #include <map

BZOJ 1967 Ahoi2005 CROSS 穿越磁场 FloodFill+BFS

题目大意:给定平面上的n个正方形,求某个点到另一个点至少穿过多少个边界 一开始想对于每个正方形判断一下起点和终点是否在同一侧= = 但是反例显然 考虑到n<=100,可以离散化一下,然后用Floodfill标记每块区域 然后跑最短路就行了--由于边权都是1,所以用BFS就能搞出最短路了 连边连挂了调了半宿-- #include <cstdio> #include <cstring> #include <iostream> #include <algorith

aoapc第六章 R题 Sculpture

aoapc第六章 R题 Sculpture http://7xjob4.com1.z0.glb.clouddn.com/5e3271c0195996a70363138f9cb82dd5 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 sc

uva oj 12171(hdu 2771)[离散化]sculptrue

以前对离散化的理解不够,所以把端点和区间区分来考虑但是做完这题以后有了新的认识: 先来看一个问题:给你以下的网格,你需要多少空间去存储红点区间的信息呢? 只需要图上所示的1,2,3,4个点就足够表示红点所在区间了,为什么不是一个区间的第一个红点和最后一个红点呢?(如果这样记录的话则必须加一区间点,记录区间内部信息,因为端点可能是两个区间的交集而区间内可能只被操作了一次)这样做的好处是空白区域的长度也能轻易计算出来. 为了计算总区间两端空白的长度,增加A和B点. 原数据找离散后的值直接二分,没必要

离散化模板

关于离散化, 推荐几篇博客 http://www.matrix67.com/blog/archives/108 http://blog.csdn.net/doyouseeman/article/details/51154142 #include<cstdio> #include<algorithm> using namespace std; int a[10001],date[10001],n; int main() { scanf("%d",&n);