题目来源: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)。

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

 //////////////////////////////////////////////////////////////////////////
// POJ1052 Plato's Blocks
// Memory: 396K Time: 16MS
// Language: C++ Result: Accepted
////////////////////////////////////////////////////////////////////////// #include <iostream> using namespace std;
int n;
int face[][][][];
int cube[][][];
int visited[][][]; bool input() {
cin >> n;
if (n == ) return false;
char c;
for (int t = ; t < ; ++t) {
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
cin >> c;
if (c == 'X') face[t][][i][j] = ;
else face[t][][i][j] = ;
}
}
}
return true;
} void r_m() {
//rotation
for (int t = ; t < ; ++t) {
for (int k = ; k <= ; ++k) {
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
face[t][k][i][j] = face[t][k - ][j][n - i - ];
}
}
}
}
//mirror
for (int t = ; t < ; ++t) {
for (int k = ; k < ; ++k) {
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
face[t][k + ][i][j] = face[t][k][i][n - j - ];
}
}
}
}
} void MakeCube(int a, int b, int c) {
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (face[][a][i][j] == ) {
for (int k = ; k < n; ++k) {
cube[i][j][k] = ;
}
}
}
}
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (face[][b][i][j] == ) {
for (int k = ; k < n; ++k) {
cube[k][i][j] = ;
}
}
}
}
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (face[][c][i][j] == ) {
for (int k = ; k < n; ++k) {
cube[i][k][j] = ;
}
}
}
}
} bool check(int a, int b, int c) {
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (face[][a][i][j] == ) {
bool flag = ;
for (int k = ; k < n; ++k) {
if (cube[i][j][k]) {
flag = ;
break;
}
}
if (flag == ) {
return false;
}
}
}
}
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (face[][b][i][j] == ) {
bool flag = ;
for (int k = ; k < n; ++k) {
if (cube[k][i][j]) {
flag = ;
break;
}
}
if (flag == ) {
return false;
}
}
}
}
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (face[][c][i][j]) {
bool flag = ;
for (int k = ; k < n; ++k) {
if (cube[i][k][j]) {
flag = ;
break;
}
}
if (flag == ) {
return false;
}
}
}
}
return true;
} void dfs(int i, int j, int k) {
if (i < || i >= n || j < || j >= n || k < || k >= n) {
return ;
}
if (cube[i][j][k] == || visited[i][j][k] == ) {
return;
}
visited[i][j][k] = ;
dfs(i - , j, k);
dfs(i + , j, k);
dfs(i, j - , k);
dfs(i, j + , k);
dfs(i, j, k - );
dfs(i, j, k + );
} bool connectivity() {
memset(visited, , sizeof(visited));
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (cube[i][j][]) {
dfs(i, j, );
for (int a = ; a < n; ++a) {
for (int b = ; b < n; ++b) {
for (int c = ; c < n; ++c) {
if (cube[a][b][c] && visited[a][b][c] == ) {
return false;
}
}
}
}
return true;
}
}
}
} bool IsValid() {
r_m();
for (int i = ; i < ; ++i) {
for (int j = ; j < ; ++j) {
for (int k = ; k < ; ++k) {
memset(cube, , sizeof(cube));
MakeCube(i, j, k);
if (check(i, j, k) && connectivity()) {
return true;
}
}
}
}
return false;
} int main(void) {
int case_id = ;
while (input()) {
cout << "Data set " << ++case_id << ": ";
if (IsValid()) {
cout << "Valid set of patterns" << endl;
} else {
cout << "Impossible combination" << endl;
}
}
system("pause");
return ;
}

POJ1052 Plato's Blocks的更多相关文章

  1. POJ 1052 Plato's Blocks

      Plato's Blocks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 734   Accepted: 296 De ...

  2. POJ题目排序的Java程序

    POJ 排序的思想就是根据选取范围的题目的totalSubmittedNumber和totalAcceptedNumber计算一个avgAcceptRate. 每一道题都有一个value,value ...

  3. POJ题目细究

    acm之pku题目分类 对ACM有兴趣的同学们可以看看 DP:  1011   NTA                 简单题  1013   Great Equipment     简单题  102 ...

  4. 【转】POJ百道水题列表

    以下是poj百道水题,新手可以考虑从这里刷起 搜索1002 Fire Net1004 Anagrams by Stack1005 Jugs1008 Gnome Tetravex1091 Knight ...

  5. 从Script到Code Blocks、Code Behind到MVC、MVP、MVVM

    刚过去的周五(3-14)例行地主持了技术会议,主题正好是<UI层的设计模式——从Script.Code Behind到MVC.MVP.MVVM>,是前一天晚上才定的,中午花了半小时准备了下 ...

  6. 【POJ-1390】Blocks 区间DP

    Blocks Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5252   Accepted: 2165 Descriptio ...

  7. 开发该选择Blocks还是Delegates

    前文:网络上找了很多关于delegation和block的使用场景,发现没有很满意的解释,后来无意中在stablekernel找到了这篇文章,文中作者不仅仅是给出了解决方案,更值得我们深思的是作者独特 ...

  8. poj 1390 Blocks

    poj 1390 Blocks 题意 一排带有颜色的砖块,每一个可以消除相同颜色的砖块,,每一次可以到块数k的平方分数.问怎么消能使分数最大.. 题解 此题在徐源盛<对一类动态规划问题的研究&g ...

  9. Java 同步代码块 - Synchronized Blocks

    java锁实现原理: http://blog.csdn.net/endlu/article/details/51249156 The synchronized keyword can be used ...

随机推荐

  1. .Net 使用 GregorianCalendar 获取任意一天为一年的第几周

    private static int GetWeekOfYear(DateTime dt) { GregorianCalendar gc = new GregorianCalendar(); int ...

  2. FMX 模态窗体

    FMX 模态窗体 dlg := TForm2.Create(nil);  dlg.ShowModal(procedure(ModalResult: TModalResult)  begin       ...

  3. 部署和调优 2.1 squid正向代理

    安装squid yum install -y squid Squid 官方网站为 http://www.squid-cache.org 打开注释掉的 cache_dir ufs / 缓存目录的位置,大 ...

  4. 【Android 多媒体应用】使用 VideoView 播放视频

    1.MainActivity.java import android.os.Bundle; import android.support.v7.app.AppCompatActivity; impor ...

  5. css垂直居中方法(二)

    第四种方法: 这个方法把一些div的显示方式设置为表格,因此我们可以使用表格的vartial-align属性. 代码如下: <!doctype html> <html lang=&q ...

  6. js分页demo

    纯js实现分页   原理:所有数据已加载好,js通过遍历部分显示,实现分页效果 html代码 <html> <head> <meta charset='utf-8'> ...

  7. struts2学习笔记(5)拦截器

    继承AbstractInterceptor类,在类中完成拦截器的功能,只需实现intercept方法即可,提供了init()和destroy()的空实现 示例:显示执行action所用的时间 ①在sr ...

  8. Replace Pioneer注册方法

    Replace Pioneer注册方法 Replace Pioneer过期后,会弹出一个注册(Registration)窗口,其中有一个试用选项(Trial License),点击Trial Lice ...

  9. 关于service和线程的区别

    主要有两方面,访问控制和功能区别 首先,service是运行在主线程上的,并不是一个新的线程 其次,service在运行的时候可以被多个activity访问和控制,而线程是不可以的 最后,servic ...

  10. centos 安装 python flask 和python3安装flask

    pip install Flask python3安装 pip3 install flask