POJ1052 Plato's Blocks

题目来源:http://poj.org/problem?id=1052

题目大意:

  把1*1*1的小立方体通过粘接相邻面组成大的立方体的形状。如下图所示:

  一层一层地堆叠,立方体从三个方向的投影会分别形成三个字母的形状:"E" "G" "B"

  科学家们想知道哪些投影形状的组合是可能出现的。写一个程序判断给定的投影图形组合是否可能出现。

输入:由一系列数据集组成。每个用例第一行为一个整数n(1<=n<=20),表示大立方体的边长。接下来的3*n行为给出的投影图形。每n行表示一个面的投影,'X'表示产生了影子,'-'表示光线穿过。n为0时表示输入结束。

输出:如果给出的组合可能产生,输出:Valid set of patterns 否则输出 Impossible combination 格式见sample.


Sample Input

5
XXXXX
X----
X--XX
X---X
XXXXX
XXXXX
X----
XXXXX
X----
XXXXX
XXXXX
X---X
XXXX-
X---X
XXXXX
3
X--
-X-
--X
XX-
XXX
-XX
-XX
XXX
XX-
0

Sample Output

Data set 1: Valid set of patterns
Data set 2: Impossible combination

本题也属于模拟吧。首先需要把题目看懂。

首先,对于每个给出的投影图像,可能对应8种情况:通过旋转和镜像的变换得到。那么三个面总共有8*8*8种组合,枚举所有的组合,能找到符合条件的立方体能说明组合是可能出现的,否则不可能。

通过正向构造立方体比较麻烦,可以用“逆向”的方法。具体来说,首先根据给定的立方体大小,首先初始化一个完整的立方体。然后对于投影图形中被光线穿透的格子,“挖”去立方体对应的部分。

然而对每个面这样处理后得到的残留图形并不一定还能形成给定的三个投影,所以需要检验。除了检验投影还要检验它的连通性(dfs)。

代码中循环很多,要小心。

  1 //////////////////////////////////////////////////////////////////////////
  2 //        POJ1052 Plato's Blocks
  3 //        Memory: 396K        Time: 16MS
  4 //        Language: C++        Result: Accepted
  5 //////////////////////////////////////////////////////////////////////////
  6 
  7 #include <iostream>
  8 
  9 using namespace std;
 10 int n;
 11 int face[3][8][20][20];
 12 int cube[20][20][20];
 13 int visited[20][20][20];
 14 
 15 bool input() {
 16     cin >> n;
 17     if (n == 0) return false;
 18     char c;
 19     for (int t = 0; t < 3; ++t) {
 20         for (int i = 0; i < n; ++i) {
 21             for (int j = 0; j < n; ++j) {
 22                 cin >> c;
 23                 if (c == 'X') face[t][0][i][j] = 1;
 24                 else face[t][0][i][j] = 0;
 25             }
 26         }
 27     }
 28     return true;
 29 }
 30 
 31 void r_m() {
 32     //rotation
 33     for (int t = 0; t < 3; ++t) {
 34         for (int k = 1; k <= 3; ++k) {
 35             for (int i = 0; i < n; ++i) {
 36                 for (int j = 0; j < n; ++j) {
 37                     face[t][k][i][j] = face[t][k - 1][j][n - i - 1];
 38                 }
 39             }
 40         }
 41     }
 42     //mirror
 43     for (int t = 0; t < 3; ++t) {
 44         for (int k = 0; k < 4; ++k) {
 45             for (int i = 0; i < n; ++i) {
 46                 for (int j = 0; j < n; ++j) {
 47                     face[t][k + 4][i][j] = face[t][k][i][n - j - 1];
 48                 }
 49             }
 50         }
 51     }
 52 }
 53 
 54 void MakeCube(int a, int b, int c) {
 55     for (int i = 0; i < n; ++i) {
 56         for (int j = 0; j < n; ++j) {
 57             if (face[0][a][i][j] == 0) {
 58                 for (int k = 0; k < n; ++k) {
 59                     cube[i][j][k] = 0;
 60                 }
 61             }
 62         }
 63     }
 64     for (int i = 0; i < n; ++i) {
 65         for (int j = 0; j < n; ++j) {
 66             if (face[1][b][i][j] == 0) {
 67                 for (int k = 0; k < n; ++k) {
 68                     cube[k][i][j] = 0;
 69                 }
 70             }
 71         }
 72     }
 73     for (int i = 0; i < n; ++i) {
 74         for (int j = 0; j < n; ++j) {
 75             if (face[2][c][i][j] == 0) {
 76                 for (int k = 0; k < n; ++k) {
 77                     cube[i][k][j] = 0;
 78                 }
 79             }
 80         }
 81     }
 82 }
 83 
 84 bool check(int a, int b, int c) {
 85     for (int i = 0; i < n; ++i) {
 86         for (int j = 0; j < n; ++j) {
 87             if (face[0][a][i][j] == 1) {
 88                 bool flag = 0;
 89                 for (int k = 0; k < n; ++k) {
 90                     if (cube[i][j][k]) {
 91                         flag = 1;
 92                         break;
 93                     }
 94                 }
 95                 if (flag == 0) {
 96                     return false;
 97                 }
 98             }
 99         }
100     }
101     for (int i = 0; i < n; ++i) {
102         for (int j = 0; j < n; ++j) {
103             if (face[1][b][i][j] == 1) {
104                 bool flag = 0;
105                 for (int k = 0; k < n; ++k) {
106                     if (cube[k][i][j]) {
107                         flag = 1;
108                         break;
109                     }
110                 }
111                 if (flag == 0) {
112                     return false;
113                 }
114             }
115         }
116     }
117     for (int i = 0; i < n; ++i) {
118         for (int j = 0; j < n; ++j) {
119             if (face[2][c][i][j]) {
120                 bool flag = 0;
121                 for (int k = 0; k < n; ++k) {
122                     if (cube[i][k][j]) {
123                         flag = 1;
124                         break;
125                     }
126                 }
127                 if (flag == 0) {
128                     return false;
129                 }
130             }
131         }
132     }
133     return true;
134 }
135 
136 void dfs(int i, int j, int k) {
137     if (i < 0 || i >= n || j < 0 || j >= n || k < 0 || k >= n) {
138         return ;
139     }
140     if (cube[i][j][k] == 0 || visited[i][j][k] == 1) {
141         return;
142     }
143     visited[i][j][k] = 1;
144     dfs(i - 1, j, k);
145     dfs(i + 1, j, k);
146     dfs(i, j - 1, k);
147     dfs(i, j + 1, k);
148     dfs(i, j, k - 1);
149     dfs(i, j, k + 1);
150 }
151 
152 
153 bool connectivity() {
154     memset(visited, 0, sizeof(visited));
155     for (int i = 0; i < n; ++i) {
156         for (int j = 0; j < n; ++j) {
157             if (cube[i][j][0]) {
158                 dfs(i, j, 0);
159                 for (int a = 0; a < n; ++a) {
160                     for (int b = 0; b < n; ++b) {
161                         for (int c = 0; c < n; ++c) {
162                             if (cube[a][b][c] && visited[a][b][c] == 0) {
163                                 return false;
164                             }
165                         }
166                     }
167                 }
168                 return true;
169             }
170         }
171     }
172 }
173 
174 bool IsValid() {
175     r_m();
176     for (int i = 0; i < 8; ++i) {
177         for (int j = 0; j < 8; ++j) {
178             for (int k = 0; k < 8; ++k) {
179                 memset(cube, 1, sizeof(cube));
180                 MakeCube(i, j, k);
181                 if (check(i, j, k) && connectivity()) {
182                     return true;
183                 }
184             }
185         }
186     }
187     return false;
188 }
189 
190 int main(void) {
191     int case_id = 0;
192     while (input()) {
193         cout << "Data set " << ++case_id << ": ";
194         if (IsValid()) {
195             cout << "Valid set of patterns" << endl;
196         } else {
197             cout << "Impossible combination" << endl;
198         }
199     }
200     system("pause");
201     return 0;
202 }
View Code
posted @ 2013-08-15 11:52  小菜刷题史  阅读(508)  评论(0编辑  收藏  举报