1030 - Image Is Everything
Time limit: 3.000 seconds
Your new company is building a robot that can hold small lightweight objects. The robot will have the intelligence to determine if an object is light enough to hold. It does this by taking pictures of the object from the 6 cardinal directions, and then inferring an upper limit on the object's weight based on those images. You must write a program to do that for the robot.
You can assume that each object is formed from an N×N×N lattice of cubes, some of which may be missing. Each 1×1×1 cube weighs 1 gram, and each cube is painted a single solid color. The object is not necessarily connected.
Input
The input for this problem consists of several test cases representing different objects. Every case begins with a line containing N, which is the size of the object ( 1N10). The next N lines are the different N×N views of the object, in the order front, left, back, right, top, bottom. Each view will be separated by a single space from the view that follows it. The bottom edge of the top view corresponds to the top edge of the front view. Similarly, the top edge of the bottom view corresponds to the bottom edge of the front view. In each view, colors are represented by single, unique capital letters, while a period (.) indicates that the object can be seen through at that location.
Input for the last test case is followed by a line consisting of the number 0.
Output
For each test case, print a line containing the maximum possible weight of the object, using the format shown below.
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) 分析:
① “看穿”的位置所对应的所有单位立方体一定都不存在;
② 根据题意,每个单位立方体各面被涂单一的颜色,则根据颜色可辨别单位立方体的存在与否,若前视图的右上角颜色A和顶视图的右下角颜色B不同,那么对应的单位立方体一定不存在;删除该立方体之后,也可能会造成新的矛盾。此处则存在删除次数的问题。 代码如下:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn = ;
int n;
char read_char()
{
char ch;
while()
{
ch = getchar();
if((ch >= 'A' && ch <= 'Z') || ch == '.') return ch;
}
}
char view[maxn][maxn][maxn];
char pos[maxn][maxn][maxn];
void get(int k, int i, int j, int len, int& x, int& y, int&z)
{//第k个视图中,第i行j列深度为len对应立方体中的坐标(x, y, z);
if(k == )//前
x = len, y = j, z = i;
if(k == )//左
x = n-j-, y = len, z = i;
if(k == )//后
x = n-len-, y = n-j-, z = i;
if(k == )//右
x = j, y = n-len-, z = i;
if(k == )//顶
x = n-i-, y = j, z = len;
if(k == )//底
x = i, y = j, z = n-len-;
}
int main()
{
while(~scanf("%d", &n) && n)
{
char ch;
for(int i = ; i < n; i ++) //第i行
for(int k = ; k < ; k++) //第j面
for(int j = ; j < n; j++) //第k列
view[k][i][j] = read_char();
for(int i = ; i < n; i ++) //
for(int j = ; j < n; j++)
for(int k = ; k < n; k++)
pos[i][j][k] = '#';
for(int k = ; k < ; k++) //第j面
for(int i = ; i < n; i++)
for(int j = ; j < n; j++)
if(view[k][i][j] == '.')
for(int l = ; l < n; l++) //深度len
{
int x, y, z;
get(k, i, j, l, x, y, z);
pos[x][y][z] = '.'; //无单位立方体的地方标志为'.'
} while()
{
bool done = true;
for(int k = ; k < ; k++) //第j面
for(int i = ; i < n; i++) //第i行
for(int j = ; j < n; j++) //第j列
if(view[k][i][j] != '.')
{
for(int l = ; l < n; l++) //深度len — 扫描
{
int x, y, z;
get(k, i, j, l, x, y, z);
if(pos[x][y][z] == '.') //若该单位立方体不存在,深度加1
continue;
if(pos[x][y][z] == '#') //若该单位立方体存在但为初始状态,则更改为即给颜色(此主要
{ //是为了判断不同面颜色是否相等,若相等则存在立方体,否则不存在
pos[x][y][z] = view[k][i][j];
break;
}
if(pos[x][y][z] == view[k][i][j]) //存在
break;
pos[x][y][z] = '.'; //不存在
done = false;
}
}
if(done) break;
}
int ans = ;
for(int i = ; i < n; i ++) //
for(int j = ; j < n; j++)
for(int k = ; k < n; k++)
{
if(pos[i][j][k] != '.') ans++;
}
printf("Maximum weight: %d gram(s)\n", ans);
}
return ;
}
其中:
char view[6][maxn][maxn]; //存储各面各位置的颜色
char pos[maxn][maxn][maxn]; //N*N*N,模拟单位立方体的存在与否
初始化
for(int i = ; i < n; i ++) //第i行
for(int k = ; k < ; k++) //第j面
for(int j = ; j < n; j++) //第k列
view[k][i][j] = read_char(); //读入颜色
for(int i = ; i < n; i ++) for(int j = ; j < n; j++)
for(int k = ; k < n; k++)
pos[i][j][k] = '#'; //第i行j列k深的单位立方体初始化为不存在
read_char()函数:
char read_char()
{
char ch;
while()
{
ch = getchar();
if((ch >= 'A' && ch <= 'Z') || ch == '.') return ch;
}
}
主函数:
①程序用了一个get函数来表示第k个视图中,第i行j列深度为len的单位正方体在原立方体中的坐标(x,y,z);
void get(int k, int i, int j, int len, int& x, int& y, int&z)
{//第k个视图中,第i行j列深度为len对应立方体中的坐标(x, y, z);
if(k == )//前
x = len, y = j, z = i;
if(k == )//左
x = n-j-, y = len, z = i;
if(k == )//后
x = n-len-, y = n-j-, z = i;
if(k == )//右
x = j, y = n-len-, z = i;
if(k == )//顶
x = n-i-, y = j, z = len;
if(k == )//底
x = i, y = j, z = n-len-;
}
②删除次数问题.
不难证明,第一次删除是必要的,再利用数学归纳法,假设前k次删除是必要的,且删除立方体之后不能解除矛盾,则第k+1次删除是必要的。
while()
{
bool done = true;
for(int k = ; k < ; k++) //第j面
for(int i = ; i < n; i++) //第i行
for(int j = ; j < n; j++) //第j列
if(view[k][i][j] != '.')
{
for(int l = ; l < n; l++) //深度len — 扫描
{
int x, y, z;
get(k, i, j, l, x, y, z);
if(pos[x][y][z] == '.') //若该单位立方体不存在,深度加1
continue;
if(pos[x][y][z] == '#') //若该单位立方体存在但为初始状态,则更改为即给颜色(此主要
{ //是为了判断不同面颜色是否相等,若相等则存在立方体,否则不存在
pos[x][y][z] = view[k][i][j];
break;
}
if(pos[x][y][z] == view[k][i][j]) //存在
break;
pos[x][y][z] = '.'; //不存在
done = false;
}
}
if(done) break;
}
最后输出,即输出pos数组中不是”."的个数。