/*
题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=747
白书对此题的评价:
本题有一定实际意义,而且需要注意细节,建议读者一试
----------------------------------------------------
参考的题解:
http://blog.csdn.net/crazysillynerd/article/details/43882593
//这个博主的题目解释,可谓是相当详细。在看书上的中文题意以后,我其实是觉得有些细节没有明白。再上 uva 看英文原题时,仍然不太明白。最后是看到这个博主的解释,我才豁然开朗...
*/
/*
借鉴思路于:
http://blog.csdn.net/u014800748/article/details/44866133
*/
#include <iostream>
#include <stack>
#include <vector>
#include <cstring>
#include <algorithm>
#define rep(i, j, n) for (int i = j; i < (n); i++)
#define Clean(i, j) memset(i, j, sizeof(i))
using namespace std;
const int N = 64 + 5;
char g[N][N];
vector<int>code;
int n;
struct Node
{
int color; //黑色或白色
int dir; // 表示方向,不同的方向 (NW、NE、SW、SE)有不同的权重
}node[N * N];
void encode(int r, int c, int w, int dir, int &id)
{ //(r, c)表示起点坐标,w表示宽度,dir表示编码后的方向,id表示结点编号(传引用使得,如果该区域确实可以用一个结点来表示,那么下次再标结点时,标号就从 id+1 开始)
int ok = 1;
char ch = g[r][c];
rep(i, r, r + w)
rep(j, c, c + w)
if (g[i][j] != ch)
{
ok = 0; //表示这个区域里有不同颜色的情况,这个区域必须划分四等分
break;
}
if (ok) //表示该区域同色,可作为一个结点处理
{
node[id].color = (ch == '0' ? 0 : 1);
int x = dir, k = 1;
stack<int> s; // 利用栈来实现五进制向十进制的转换
while (x > 0)
{
s.push(x % 10);
x /= 10;
}
while ( !s.empty() )
{
node[id].dir += s.top() * k; s.pop();
k *= 5;
}
id++;
}
else //该区域有不同色,则分为四个区域,递归编码
{
encode ( r, c, w / 2, dir * 10 + 1, id );
encode ( r, c + w / 2, w / 2, dir * 10 + 2, id );
encode ( r + w / 2, c, w / 2, dir * 10 + 3, id );
encode ( r + w / 2, c + w / 2, w / 2, dir * 10 + 4, id);
}
}
void draw (int r, int c, int w)
{
rep(i, r, r + w) rep(j, c, c + w)
g[i][j] = '*';
}
void decode(vector<int> s)
{
int size = (int)s.size();
rep(i, 0, size)
{
int x = s[i], k = 1;
node[i].color = 1;
while (x > 0) //解码路径,低位是靠近树根的路径
{
node[i].dir += ( x % 5 ) * k;
x /= 5, k *= 10;
}
}
rep(i, 0, size)
{
int dir = node[i].dir;
int r = 0, c = 0, w = n;
while (dir > 0) //沿路径找区域
{
int x = dir % 10; //越是靠近各位的位,对应的是越靠近根节点的路径,从根出发,所以从个位开始
w /= 2, dir /= 10; //注意此时的 w 已经减半了,所以后面累加到 r 或是 c 上时,不必再减半
if (x == 2) c += w;
else if (x == 3) r += w;
else if (x == 4) c += w, r += w;
}
draw(r, c, w);
}
rep(i, 0, n) rep(j, 0, n)
if (g[i][j] != '*') g[i][j] = '.';
rep(i, 0, n) puts(g[i]);
}
void solve()
{
int kase = 0;
while ( scanf("%d", &n), n )
{
Clean(g, '\0');
Clean(node, 0);
if (kase) printf("\n");
printf("Image %d\n", ++kase);
if (n > 0)
{
rep(i, 0, n) scanf("%s", g[i]);
int id = 1;
encode(0, 0, n, 0, id); //编码整张图
vector<int> ans;
rep(i, 1, id) if (node[i].color == 1) ans.push_back(node[i].dir);
sort(ans.begin(), ans.end());
rep(i, 0, (int)ans.size())
{
printf("%d", ans[i]);
if ( (i + 1) % 12 == 0 || i == (int)ans.size() - 1) printf("\n");
else printf(" ");
}
printf("Total number of black nodes = %d\n", (int)ans.size());
}
else
{
code.clear();
n = -n;
int x;
while (scanf("%d", &x) && x != -1) code.push_back(x);
decode(code); //解码,画图
}
}
}
int main()
{
solve();
return 0;
}
/*
查阅的其他资料:
https://zhidao.baidu.com/question/578232457.html
http://blog.csdn.net/xingjiarong/article/details/47282817
*/