UVA

来源:互联网 发布:网络兼职打字员靠谱吗 编辑:程序博客网 时间:2024/06/06 07:21
/*题目链接: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.htmlhttp://blog.csdn.net/xingjiarong/article/details/47282817*/




原创粉丝点击