描述
题解
这个题是 51Nod 五级题中少有的思路明确的题,在我看来,这一定是 AC 人数和题目难度最不成正比的一道题……
总的来说,这个题不过是三视图和雕塑的正逆转换。
凡是可能有雕塑的地方我们每次++,如果这个地方可以有,那么经过三视图一折腾,A[x][y][z] 一定为 3,这里问是否有可能,那么此时所有标记为 3 的组合在一起可能并不符合连通,但是我们可以通过选取其中连通的进行判定是否符合三视图,所以这个问题也就是正着来一遍建三维雕塑,然后经过 dfs() 所有联通块儿,每次 dfs() 完后将选取的部分放在另一个 A_[x][y][z] 中,然后对这个三维数组进行判定是否可以构成题目给定的三视图。存在雕塑可以是虚无的哲学思维……也就是三视图中从来没有出现过一次 Y,这种情况是 Possible
的……这个题没有涉及什么难的算法,最难的也就是一个基础的 dfs(),所以为啥只有不到十个人 AC 啊……
代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 13;
const int DIR[6][3] = {{0, 0, 1}, {0, 0, -1},
{0, 1, 0}, {0, -1, 0},
{1, 0, 0}, {-1, 0, 0}};
int N, cnt;
int A[MAXN][MAXN][MAXN];
int A_[MAXN][MAXN][MAXN];
int vis[MAXN][MAXN][MAXN];
char s1[MAXN][MAXN];
char s2[MAXN][MAXN];
char s3[MAXN][MAXN];
int charge(int x, int y, int z)
{
if (x < 0 || x >= N)
{
return 0;
}
if (y < 0 || y >= N)
{
return 0;
}
if (z < 0 || z >= N)
{
return 0;
}
if (vis[x][y][z])
{
return 0;
}
if (A[x][y][z] < 3)
{
return 0;
}
return 1;
}
void dfs(int x, int y, int z)
{
for (int i = 0; i < 6; i++)
{
int x_ = x + DIR[i][0];
int y_ = y + DIR[i][1];
int z_ = z + DIR[i][2];
if (charge(x_, y_, z_))
{
vis[x_][y_][z_] = 1;
A_[x_][y_][z_] = 3;
dfs(x_, y_, z_);
}
}
}
int charge_()
{
int flag;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (s1[i][j] == 'Y')
{
flag = 1;
for (int k = 0; k < N; k++)
{
if (A_[i][j][k] == 3)
{
flag = 0;
break;
}
}
if (flag)
{
return 0;
}
}
}
}
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (s2[i][j] == 'Y')
{
flag = 1;
for (int k = 0; k < N; k++)
{
if (A_[k][i][j] == 3)
{
flag = 0;
break;
}
}
if (flag)
{
return 0;
}
}
}
}
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (s3[i][j] == 'Y')
{
flag = 1;
for (int k = 0; k < N; k++)
{
if (A_[j][k][i] == 3)
{
flag = 0;
break;
}
}
if (flag)
{
return 0;
}
}
}
}
return 1;
}
int main(int argc, const char * argv[])
{
// freopen("/Users/zyj/Desktop/input.txt", "r", stdin);
int T;
cin >> T;
while (T--)
{
memset(A, 0, sizeof(A));
memset(vis, 0, sizeof(vis));
cin >> N;
int flag = 0;
for (int i = 0; i < N; i++)
{
scanf("%s", s1[i]);
for (int j = 0; j < N; j++)
{
if (s1[i][j] == 'Y')
{
flag = 1;
for (int k = 0; k < N; k++)
{
A[i][j][k]++;
}
}
}
}
for (int i = 0; i < N; i++)
{
scanf("%s", s2[i]);
for (int j = 0; j < N; j++)
{
if (s2[i][j] == 'Y')
{
flag = 1;
for (int k = 0; k < N; k++)
{
A[k][i][j]++;
}
}
}
}
for (int i = 0; i < N; i++)
{
scanf("%s", s3[i]);
for (int j = 0; j < N; j++)
{
if (s3[i][j] == 'Y')
{
flag = 1;
for (int k = 0; k < N; k++)
{
A[j][k][i]++;
}
}
}
}
if (!flag)
{
cout << "Possible\n";
continue;
}
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
for (int k = 0; k < N; k++)
{
if (!vis[i][j][k] && A[i][j][k] == 3)
{
memset(A_, 0, sizeof(A_));
vis[i][j][k] = 1;
A_[i][j][k] = 3;
dfs(i, j, k);
if (charge_())
{
cout << "Possible\n";
goto cn;
}
}
}
}
}
cout << "Impossible\n";
cn:
;
}
return 0;
}