https://vjudge.net/problem/UVA-1030
题目
有个机器人会对一个由相同大小的正方体组成的物品拍照(这个物品不一定是一块),每个侧面都会拍一张,并且计算最大重量(一个小正方体重1g,六个面颜色相同),你需要编写确定重量的程序。如果颜色为“.”表示这个位置直接可以看穿这个物品。
Sample Input
3 .R. YYR .Y. RYY .Y. .R. GRB YGR BYG RBY GYB GRB .R. YRR .Y. RRY .R. .Y. 2 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ 0
Sample Output
Maximum weight: 11 gram(s) Maximum weight: 8 gram(s)
题解
首先看作整体,然后运用归纳法,删除存在矛盾的方块,同时标记受到影响的方块,在下一次检测它们。
矛盾只能靠删除解决,而且对于一个有矛盾的方块来说,删除其他方块不能消除颜色的矛盾。
AC代码
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cctype> #include<unordered_map> #define REP(i,a,b) for(register int i=(a); i<(b); i++) #define REPE(i,a,b) for(register int i=(a); i<=(b); i++) #define PERE(i,a,b) for(register int i=(a); i>=(b); i--) using namespace std; typedef long long ll; int n; char sfs[6][10][10]; struct node { char m[6]; bool no, vis; }; node fks[10][10][10]; inline void paint() { REP(i,0,n) REP(j,0,n) REP(k,0,n) memset(&fks[i][j][k],0,sizeof(fks[i][j][k])); PERE(y,n-1,0) REP(x,0,n) fks[x][y][0].m[0]=sfs[0][n-1-y][x]; //0 PERE(y,n-1,0) PERE(z,n-1,0) fks[0][y][z].m[1]=sfs[1][n-1-y][n-1-z]; //1 PERE(y,n-1,0) PERE(x,n-1,0) fks[x][y][n-1].m[2]=sfs[2][n-1-y][n-1-x]; //2 PERE(y,n-1,0) REP(z,0,n) fks[n-1][y][z].m[3]=sfs[3][n-1-y][z]; //3 PERE(z,n-1,0) REP(x,0,n) fks[x][n-1][z].m[4]=sfs[4][n-1-z][x]; //4 REP(z,0,n) REP(x,0,n) fks[x][0][z].m[5]=sfs[5][z][x]; //5 } struct id { char x,y,z; }; queue<id> q; int ans; inline void del(int x, int y, int z) { #define A(a,b,c) if(!fks[a][b][c].vis) {fks[a][b][c].vis=1; q.push((id){(char)(a),(char)(b),(char)(c)});} fks[x][y][z].no=true; if(fks[x][y][z].m[0]) REP(i,z+1,n) if(!fks[x][y][i].no) {fks[x][y][i].m[0]=fks[x][y][z].m[0]; A(x,y,i); break;} if(fks[x][y][z].m[1]) REP(i,x+1,n) if(!fks[i][y][z].no) {fks[i][y][z].m[1]=fks[x][y][z].m[1]; A(i,y,z); break;} if(fks[x][y][z].m[2]) PERE(i,z-1,0) if(!fks[x][y][i].no) {fks[x][y][i].m[2]=fks[x][y][z].m[2]; A(x,y,i); break;} if(fks[x][y][z].m[3]) PERE(i,x-1,0) if(!fks[i][y][z].no) {fks[i][y][z].m[3]=fks[x][y][z].m[3]; A(i,y,z); break;} if(fks[x][y][z].m[4]) PERE(i,y-1,0) if(!fks[x][i][z].no) {fks[x][i][z].m[4]=fks[x][y][z].m[4]; A(x,i,z); break;} if(fks[x][y][z].m[5]) REP(i,y+1,n) if(!fks[x][i][z].no) {fks[x][i][z].m[5]=fks[x][y][z].m[5]; A(x,i,z); break;} ans++; } bool isok(int x, int y, int z) { char col=0; REP(i,0,6) if(fks[x][y][z].m[i]!=0) {col=fks[x][y][z].m[i]; break;} if(col=='.') return false; if(col==0) return true; REP(i,0,6) if(fks[x][y][z].m[i]!=0 && fks[x][y][z].m[i]!=col) return false; return true; } int main() { while(~scanf("%d", &n) && n) { ans=0; REP(i,0,n) REP(k,0,6) REP(j,0,n) { sfs[k][i][j]=getchar(); if(sfs[k][i][j]<=' ') sfs[k][i][j]=getchar(); } paint(); REP(i,0,n) REP(j,0,n) { if(!isok(i,j,0)) A(i,j,0); if(!isok(i,j,n-1)) A(i,j,n-1); } REP(i,0,n) REP(k,0,n) { if(!isok(i,0,k)) A(i,0,k); if(!isok(i,n-1,k)) A(i,n-1,k); } REP(j,0,n) REP(k,0,n) { if(!isok(0,j,k)) A(0,j,k); if(!isok(n-1,j,k)) A(n-1,j,k); } while(!q.empty()) { id now = q.front(); q.pop(); fks[now.x][now.y][now.z].vis=0; if(!isok(now.x, now.y, now.z)) del(now.x, now.y, now.z); } printf("Maximum weight: %d gram(s) ", n*n*n-ans); } }