z这题没有ac,但是试了无数的数据和刘汝佳的做了对比,没有看出哪里有错来
说说这题学到了什么:
第一DFS很容易栈溢出,最好使用BFS
另外在使用BFS的时候,元素一入队,就必须设置vis,否则会导致同一个元素重复入队
第二,像这种坐标类型的题目,坐标之间的关系一定要弄清楚,清除的意思是一目了然,不需要动手去计算,如果需要动手计算的话,那么编程实现起来会很困难
下面附上我写的代码,真心不知道哪里错了
//这道题目使用的floodfill倒是不难,难的是离散化的过程中,如何确定各个离散化后的立体块的颜色 //昨天想了半天也没有想出来 //还有一个原因是坐标和对应要涂色的块的对应关系没有搞清楚(其实这点才是主要原因) //在color上的xyz坐标就是在对应的已经离散了的坐标里面是从第x个坐标到x+1个坐标对应的长度,而他的第x个坐标存在离散化数组的x-1个元素当中 #include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<cstring> using namespace std; const int maxn = 100 + 10; int x0[50 + 5],x[50 + 5],Y0[50 + 5],y[50 + 5],z0[50 + 5],z[50 + 5]; int dx[maxn],dy[maxn],dz[maxn]; int num_dx,num_dy,num_dz; int cnt = 2; int color[maxn][maxn][maxn]; bool is_in_cube(int x,int y,int z) { if(x >= 0 && y >= 0 && z >= 0 && x < num_dx - 1 && y < num_dy - 1 && z < num_dz - 1) return true; return false; } int Dx[6] = {0,0,0,0,1,-1}; int Dy[6] = {1,-1,0,0,0,0}; int Dz[6] = {0,0,1,-1,0,0}; int volume = 0; int area = 0; int compute(int x,int y,int z,int i) { if(i == 0 || i == 1)//x*y就可以了 { return (dx[x + 1] - dx[x]) * (dz[z + 1] - dz[z]); } if(i == 2 || i == 3) { return (dx[x + 1] - dx[x]) * (dy[y + 1] - dy[y]); } if(i == 4 || i == 5) { return (dz[z + 1] - dz[z]) * (dy[y + 1] - dy[y]); } } struct node { int x,y,z; node(int a = 0,int b = 0,int c = 0):x(a),y(b),z(c){} }; //void DFS(int x,int y,int z) //{ // color[x][y][z] = cnt; // volume = volume + (dx[x + 1] - dx[x]) * (dy[y + 1] - dy[y]) * (dz[z + 1] - dz[z]); // for(int i_0 = 0;i_0 < 6;i_0++) // { // int X = x + Dx[i_0]; // int Y = y + Dy[i_0]; // int Z = z + Dz[i_0]; // if(is_in_cube(X,Y,Z)) // { // if(color[X][Y][Z] == 1)//旁边是一个涂为1的块,这个时候需要计算面积 // { // area = area + compute(x,y,z,i_0); // } // if(!color[X][Y][Z]) // { // DFS(X,Y,Z); // } // } // } //} int main() { #ifdef local freopen("out.txt","r",stdin); freopen("output2.txt","w",stdout); #endif int kase; scanf("%d",&kase); for(int i_1 = 0;i_1 < kase;i_1++) { area = 0; volume = 0; memset(color,0,sizeof(color)); memset(dx,0,sizeof(dx)); memset(dy,0,sizeof(dy)); memset(dz,0,sizeof(dz)); int num_cube; scanf("%d",&num_cube); for(int i_2 = 0;i_2 < num_cube;i_2++) { scanf("%d%d%d%d%d%d",&x0[i_2],&Y0[i_2],&z0[i_2],&x[i_2],&y[i_2],&z[i_2]); dx[2 * i_2] = x0[i_2]; dx[2 * i_2 + 1] = x0[i_2] + x[i_2]; dy[2 * i_2] = Y0[i_2]; dy[2 * i_2 + 1] = Y0[i_2] + y[i_2]; dz[2 * i_2] = z0[i_2]; dz[2 * i_2 + 1] = z0[i_2] + z[i_2]; } dx[2 * num_cube] = 0; dx[2 * num_cube + 1] = 1000 + 1; dy[2 * num_cube] = 0; dy[2 * num_cube + 1] = 1000 + 1; dz[2 * num_cube] = 0; dz[2 * num_cube + 1] = 1000 + 1;//这样的话,最后一层包着的一定是空的 sort(dx,dx + 2 * (num_cube + 1)); sort(dy,dy + 2 * (num_cube + 1)); sort(dz,dz + 2 * (num_cube + 1)); num_dx = unique(dx,dx + 2 * (num_cube + 1)) - dx;//从0开始一直到505,一共有多少个坐标,但是一定少于110个 num_dy = unique(dy,dy + 2 * (num_cube + 1)) - dy; num_dz = unique(dz,dz + 2 * (num_cube + 1)) - dz; for(int i_3 = 0; i_3 < num_cube ;i_3++) { int DX1 = lower_bound(dx,dx + num_dx,x0[i_3]) - dx ; int DX2 = lower_bound(dx,dx + num_dx,x0[i_3] + x[i_3]) - dx ; int DY1 = lower_bound(dy,dy + num_dx,Y0[i_3]) - dy ; int DY2 = lower_bound(dy,dy + num_dy,Y0[i_3] + y[i_3]) - dy ; int DZ1 = lower_bound(dz,dz + num_dz,z0[i_3]) - dz ; int DZ2 = lower_bound(dz,dz + num_dz,z0[i_3] + z[i_3]) - dz ;//各自是第几个坐标 for(int j_0 = DX1;j_0 < DX2;j_0++) { for(int j_1 = DY1;j_1 < DY2;j_1++) { for(int j_2 = DZ1; j_2 < DZ2;j_2++) { color[j_0][j_1][j_2] = 1;//给属于立方块的坐标块涂色 } } } } node fir; queue<node>Q; Q.push(fir); color[fir.x][fir.y][fir.z] = 2; while(!Q.empty()) { node u = Q.front(); Q.pop(); //color[u.x][u.y][u.z] = 2; volume += (dx[u.x + 1] - dx[u.x]) * (dy[u.y + 1] - dy[u.y]) * (dz[u.z + 1] - dz[u.z]); for(int i = 0;i < 6;i++) { int x = u.x + Dx[i]; int y = u.y + Dy[i]; int z = u.z + Dz[i]; if(is_in_cube(x,y,z)) { if(color[x][y][z] == 1) area += compute(u.x,u.y,u.z,i); if(!color[x][y][z]) { node v(x,y,z); color[x][y][z] = 2;//即将要入队的时候,必须要涂色,否则的话会导致重复入队 Q.push(v); } } } } printf("%d ",area); printf("%d\n",dx[num_dx - 1] * dy[num_dy - 1] * dz[num_dz - 1] - volume); } return 0; }