hdu 2771(uva 12171) Sculpture bfs+离散化
题意:
给出一些边平行于坐标轴的长方体,这些长方体可能相交。也可能相互嵌套。这些长方体形成了一个雕塑,求这个雕塑的整体积和表面积。
题解:
最easy想到直接进行bfs或者dfs统计,但此题的麻烦之处在于求整个雕塑的外表面积和雕塑内部可能出现四个长方体所搭成的空心。空心不能计算到表面积中,可是计算整体积却要计入,于是直接bfs或者dfs不优点理。于是,能够想到直接统计整个雕塑外围的全部小方块。就可以非常方便地求出雕塑地表面积和体积(雕塑地整体积==整个空间地体积-外围想方块的体积),另一点就是因为坐标范围达到1-1000,
整个空间的大小达到了1000*1000*1000 = 1e9, 直接bfs明显会超时,因为长方体的个数最大仅仅有50个,于是能够对原坐标进行离散化,把每一维的坐标离散化后,整个空间的大小缩小到了100*100*100 = 1e6,于是这个问题就攻克了。
(具体參考代码。凝视地非常具体)。
代码:(參考了标程。非常美丽地代码)
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 50 + 5;
const int maxc = 1000 + 1; int n;
int x0[maxn], y0[maxn], z0[maxn], x1[maxn], y1[maxn], z1[maxn];
int xs[maxn*2], ys[maxn*2], zs[maxn*2], nx, ny, nz;
int color[maxn*2][maxn*2][maxn*2];
int dx[] = {0, 0, 0, 0, -1, 1};
int dy[] = {0, 0, -1, 1, 0, 0};
int dz[] = {-1, 1, 0, 0, 0, 0}; struct Cell
{
int x, y, z;
Cell(int x = 0, int y = 0, int z = 0) : x(x), y(y), z(z) {}
void setVis() const {
color[x][y][z] = 2;
}
int volume() const {
return (xs[x+1]-xs[x])*(ys[y+1]-ys[y])*(zs[z+1]-zs[z]);
}
Cell neighbor(int i) const {
return Cell(x+dx[i], y+dy[i], z+dz[i]);
}
bool valid() const {
return x>=0 && x<nx-1 && y>=0 && y<ny-1 && z>=0 && z<nz-1;
}
bool solid() const {
return color[x][y][z] == 1;
}
int area(int i) const {
if (dx[i] != 0) return (ys[y+1]-ys[y])*(zs[z+1]-zs[z]);
else if(dy[i] != 0) return (xs[x+1]-xs[x])*(zs[z+1]-zs[z]);
else return (xs[x+1]-xs[x])*(ys[y+1]-ys[y]);
}
bool getVis() const {
return color[x][y][z] == 2;
}
}; void discretize(int* x, int& n) //对每一维进行离散化
{
sort(x, x + n);
n = (int)(unique(x, x+n) - x);
}
int ID(int* x, int n, int x0) //找到原坐标离散化后的新坐标
{
return (int)(lower_bound(x, x+n, x0) - x);
}
void floodfill(int& s, int& v) //bfs 统计
{
s = v = 0;
Cell c; c.setVis();
queue<Cell> Q; Q.push(c); while (!Q.empty())
{
Cell now = Q.front(); Q.pop();
v += now.volume(); //统计雕塑外围的整体积
for (int i = 0; i < 6; i++)
{
Cell nxt = now.neighbor(i);
if (!nxt.valid()) continue; //越界
if (nxt.solid()) s += now.area(i); //统计雕塑外围表面积
else if(!nxt.getVis())
{
nxt.setVis();
Q.push(nxt);
}
}
}
v = maxc*maxc*maxc - v; //雕塑体积 == 整个空间的体积-雕塑外围体积
}
int main()
{
// freopen("/Users/apple/Desktop/in.txt", "r", stdin); int t; scanf("%d", &t); while (t--)
{
scanf("%d", &n);
nx = ny = nz = 2;
xs[0] = ys[0] = zs[0] = 0;
xs[1] = ys[1] = zs[1] = maxc; //存入边界坐标
for (int i = 0; i < n; i++)
{
scanf("%d%d%d", &x0[i], &y0[i], &z0[i]);
scanf("%d%d%d", &x1[i], &y1[i], &z1[i]);
x1[i] += x0[i], y1[i] += y0[i], z1[i] += z0[i];
xs[nx++] = x0[i], xs[nx++] = x1[i];
ys[ny++] = y0[i], ys[ny++] = y1[i];
zs[nz++] = z0[i], zs[nz++] = z1[i];
}
discretize(xs, nx), discretize(ys, ny), discretize(zs, nz);
memset(color, 0, sizeof(color)); //染色
for (int i = 0; i < n; i++)
{
int X1 = ID(xs, nx, x0[i]), X2 = ID(xs, nx, x1[i]);
int Y1 = ID(ys, ny, y0[i]), Y2 = ID(ys, ny, y1[i]);
int Z1 = ID(zs, nz, z0[i]), Z2 = ID(zs, nz, z1[i]);
for (int X = X1; X < X2; X++) //对离散化后的坐标依次染色
{
for (int Y = Y1; Y < Y2; Y++)
{
for (int Z = Z1; Z < Z2; Z++)
{
color[X][Y][Z] = 1;
}
}
}
}
int s, v;
floodfill(s, v);
printf("%d %d\n", s, v);
} return 0;
}
hdu 2771(uva 12171) Sculpture bfs+离散化的更多相关文章
- Uva 12171 Sculpture - 离散化 + floodfill
题目连接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- UVA 12171 Sculpture
https://vjudge.net/problem/UVA-12171 题目 某人设计雕塑,用的是很扯的方法:把一堆长方体拼起来.给出长方体的坐标和长宽高,求外表面积.因为要将这雕塑进行酸洗,需要知 ...
- HDU 2717 Catch That Cow --- BFS
HDU 2717 题目大意:在x坐标上,农夫在n,牛在k.农夫每次可以移动到n-1, n+1, n*2的点.求最少到达k的步数. 思路:从起点开始,分别按x-1,x+1,2*x三个方向进行BFS,最先 ...
- UVA 12171 (hdu 2771)sculptrue(离散化)
以前对离散化的理解不够,所以把端点和区间区分来考虑但是做完这题以后有了新的认识: 先来看一个问题:给你以下的网格,你需要多少空间去存储红点区间的信息呢? 只需要图上所示的1,2,3,4个点就足够表示红 ...
- uva 12171 hdu 1771 Sculpture
//这题从十一点开始写了四十分钟 然后查错一小时+ 要吐了 这题题意是给很多矩形的左下角(x,y,z最小的那个角)和三边的长(不是x,y,z最大的那个角T-T),为组成图形的面积与表面积(包在内部的之 ...
- UVa 12171 (离散化 floodfill) Sculpture
题意: 三维空间中有n个长方体组成的雕塑,求表面积和体积. 分析: 我们可以在最外边加一圈“空气”,然后求空气的连通块的体积,最后用总体积减去即是雕塑的体积. 还有一个很“严重”的问题就是5003所占 ...
- HDU 5876 关于补图的bfs
1.HDU 5876 Sparse Graph 2.总结:好题,把STL都过了一遍 题意:n个点组成的完全图,删去m条边,求点s到其余n-1个点的最短距离. 思路:把点分为两个集合,A为所有没有到达 ...
- hdu 1240:Asteroids!(三维BFS搜索)
Asteroids! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- HDU(1175),连连看,BFS
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1175 越学越不会,BFS还是很高级的. 连连看 Time Limit: 20000/100 ...
随机推荐
- 【Fiddler】Fiddler抓包
简述 在调试H5页面.APP的网络请求时,常用Fiddler进行抓包,查看网络报文是否如我们设想.当然,Fiddler也可对我们电脑端发出HTTP请求进行抓包. Fiddler是以代理的形式运行的,即 ...
- kafka消费者如何才能从头开始消费某个topic的全量数据
消费者要从头开始消费某个topic的全量数据,需要满足2个条件(spring-kafka): (1)使用一个全新的"group.id"(就是之前没有被任何消费者使用过); (2)指 ...
- 说说Python程序的执行过程
1. Python是一门解释型语言? 我初学Python时,听到的关于Python的第一句话就是,Python是一门解释性语言,我就这样一直相信下去,直到发现了*.pyc文件的存在.如果是解释型语言, ...
- hdu3926(判断两个图是否相似,模版)
题意:给你2个图,最大度为2.问两个图是否相似. 思路:图中有环.有链,判断环的个数以及每个环组成的人数,还有链的个数以及每个链组成的人数 是否相等即可. 如果形成了环,那么每形成一个环,结点数就会多 ...
- [转]JAVA泛型通配符T,E,K,V区别,T以及Class<T>,Class<?>的区别
原文地址:https://www.jianshu.com/p/95f349258afb 1. 先解释下泛型概念 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被 ...
- Java多线程系列——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
- WPF中的命令简介
使用Prism委托命令Demo: WPF委托命令DelegateCommand的传参方式 在WPF中使用命令的步骤很简单 1.创建命令 2.绑定命令 3.设置命令源 4.设置命令目标 WPF中命令的核 ...
- JVM内存的设置
一.JVM内存的设置的原理 默认的java虚拟机的大小比较小,在对大数据进行处理时java就会报错:java.lang.OutOfMemoryError. 设置jvm内存的方法,对于单独的.class ...
- Android——计算器第一次完善
完善: 1- 处理首位为0 2- 处理首位为“.” 3- 处理前两位为“0.”,此时首位为0,但是不能处理 4- 处理小数点不能重复输入 发现bug:12.3x6 = 如下图: xml <?xm ...
- 最重要的7个Drupal内核模板文件
Drupal内核拥有40多个模板文件,其中最重要的有7个.它们组成了页面的主要部分,在定制Drupal主题时经常要用到.因此列表如下供大家参考. 模板名 原始位置 用途 html.tpl.php mo ...