uva12171 sculpture 离散化 3维bfs求面积体积
2016-08-05 00:28
253 查看
离散化。
状态数组是关键。
求面积利用投影和6个方向就可以解决。
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24845
看了很久才看懂,代码是网上找的,注释是自己写的,终于理解透彻了。
离散化>>bfs
求面积:一个实点利用投影和6个方向可以求得。求垂直于遍历方向的面。
求体积:利用一个实点直接求得。//此题不行,需要先计算空气的体积然后相减,空气的体积利用遍历空气求得。
状态数组的使用很是关键。
状态数组是关键。
求面积利用投影和6个方向就可以解决。
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24845
看了很久才看懂,代码是网上找的,注释是自己写的,终于理解透彻了。
离散化>>bfs
求面积:一个实点利用投影和6个方向可以求得。求垂直于遍历方向的面。
求体积:利用一个实点直接求得。//此题不行,需要先计算空气的体积然后相减,空气的体积利用遍历空气求得。
状态数组的使用很是关键。
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<queue> #include<vector> #include<map> #include<stack> #include<string> using namespace std; int u[6]={0,0,0,0,1,-1};//x的状态 int v[6]={1,-1,0,0,0,0};//y的状态 int w[6]={0,0,1,-1,0,0};//z的状态 struct rec{//用于输入时的值 int x1,y1,z1,x2,y2,z2; }; struct POINT{//点 int x,y,z; }; bool vis[103][103][103];//访问过的点 bool loc[103][103][103];//保存墙的点,只保存一个角的点,利用bfs梯度计算 int n,T,ans1,ans2;//面积和体积 int x[103],y[103],z[103];//用于离散化 rec p[103];//保存长方体的值 int numx,numy,numz;//保存最大值,用于最后的输出 int IDX(int aim){//用于返回长方体的位置 return lower_bound(x,x+numx,aim)-x; } int IDY(int aim){ return lower_bound(y,y+numy,aim)-y; } int IDZ(int aim){ return lower_bound(z,z+numz,aim)-z; } /* *因为减一如果探测到的话,那么表示的是投影,面积一样,比如x方向插入那么计算的是垂直的面的面积 */ int solve(int flag,int nowx,int nowy,int nowz){//计算表面积 if (flag==0) return (x[nowx+1]-x[nowx])*(z[nowz+1]-z[nowz]); if (flag==1) return (x[nowx+1]-x[nowx])*(z[nowz+1]-z[nowz]); if (flag==2) return (x[nowx+1]-x[nowx])*(y[nowy+1]-y[nowy]); if (flag==3) return (x[nowx+1]-x[nowx])*(y[nowy+1]-y[nowy]); if (flag==4) return (z[nowz+1]-z[nowz])*(y[nowy+1]-y[nowy]); if (flag==5) return (z[nowz+1]-z[nowz])*(y[nowy+1]-y[nowy]); return -1; } void bfs(){ queue<POINT> q;//bfs() q.push((POINT){0,0,0}); ans2=(x[1]-x[0])*(y[1]-y[0])*(z[1]-z[0]); vis[0][0][0]=1; while (!q.empty()) { POINT now=q.front(); q.pop(); for (int i=0;i<6;i++) {//6个方向进行bfs int tx=now.x+u[i]; int ty=now.y+v[i]; int tz=now.z+w[i]; if (tx<0 || tx>=numx-1 || ty<0 || ty>=numy-1 || tz<0 || tz>=numz-1 || vis[tx][ty][tz]) continue;//保证不出界且没有访问过 if (loc[tx][ty][tz]) {//遇到实点则计算面积,由于有6个方向遍历,所以可以访问完6个面。 ans1+=solve(i,now.x,now.y,now.z); } else { ans2+=(x[tx+1]-x[tx])*(y[ty+1]-y[ty])*(z[tz+1]-z[tz]);//计算空气的面积 vis[tx][ty][tz]=1; q.push((POINT){tx,ty,tz});//以空气节点为核心遍历 } } } } int main(){ scanf("%d",&T); for (int cas=1;cas<=T;cas++){ scanf("%d",&n); for (int i=0;i<n;i++){ scanf("%d%d%d%d%d%d",&p[i].x1,&p[i].y1,&p[i].z1,&p[i].x2,&p[i].y2,&p[i].z2); p[i].x2+=p[i].x1; p[i].y2+=p[i].y1; p[i].z2+=p[i].z1; x[2*i+1]=p[i].x1;//0位不保存值,用于第一个空气遍历 x[2*i+2]=p[i].x2; y[2*i+1]=p[i].y1; y[2*i+2]=p[i].y2; z[2*i+1]=p[i].z1; z[2*i+2]=p[i].z2; } x[0]=0; y[0]=0; z[0]=0; x[2*n+1]=1001; y[2*n+1]=1001;//表明最大值,边界 z[2*n+1]=1001;//拓展范围 sort(x,x+2*n+2); sort(y,y+2*n+2); sort(z,z+2*n+2); numx=unique(x,x+2*n+2)-x; numy=unique(y,y+2*n+2)-y; numz=unique(z,z+2*n+2)-z;//离散化 memset(loc,0,sizeof(loc)); memset(vis,0,sizeof(vis)); for (int now=0;now<n;now++){//将内部长方形包裹住,所以面积不重复计算,但是相当于把壳分成很多块儿计算。小的体积算在大的之内 for (int i=IDX(p[now].x1);i<IDX(p[now].x2);i++){ for (int j=IDY(p[now].y1);j<IDY(p[now].y2);j++){ for (int k=IDZ(p[now].z1);k<IDZ(p[now].z2);k++){ loc[i][j][k]=1;//记录矩形位置,只保存一个角 } } } } ans1=0;//^2 ans2=0;//^3 bfs(); ans2=x[numx-1]*y[numy-1]*z[numz-1]-ans2;//总体积减去空气体积 printf("%d %d\n",ans1,ans2); } return 0; }
相关文章推荐
- UVA 12171 Sculpture 离散化 floodfil 立方体体积并 转换
- UVa 12171 (离散化 floodfill) Sculpture
- UVa12171 Sculpture 离散化+搜索
- UVA12171_Sculpture_坐标旋转45度映射&&离散化
- UVA 12171 (hdu 2771)sculptrue(离散化)
- UVa 12171 Sculpture
- UVA - 12171 Sculpture
- UVa-12069-Robots inside the Labyrinth (离散化+bfs)
- UVa12171 Sculpture
- UVA - 12171 Sculpture(离散化+bfs)
- uva 12171 hdu 1771 Sculpture
- UVALive 6658 - Fiasco(BFS)
- UVA 10603 - Fill BFS~
- UVa 11624 - Fire!(BFS)
- hdu5925 离散化+bfs
- UVA-10047 The Monocycle (图的BFS遍历)
- UVA 11624 - Fire!(BFS)
- 给定半径求周长、面积、表面积、体积
- uvalive 6888 Ricochet Robots bfs
- UVA 1331 Minimax Triangulation 最大面积最小的三角剖分(区间dp--记忆化搜索)