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);
}
}