UVa 1103 - Ancient Messages [进制转换+DFS]
2016-05-17 19:34
549 查看
题目链接:点击打开链接
DFS求连通块的题目,看了好几遍题解才真正弄懂,其实算法并不难,对我而言难的是从题目中读懂题意找到思路,很感谢网上详细明了的题解。
提意简述:给定象形符号的十六制表示方法,找到对应的象形符号,并按字典序递增的顺序输出所有的象形符号。
思路:先将给定的十六进制H*W矩阵先转化成二进制H*(4*W)矩阵,此时0代表空白,1代表黑点(象形符号由1组成)。由于每个象形符号内部含有的空白洞的个数均不相同,所以可以将每个象形符号所含有的空白洞的个数作为与其他符号区别开的”特征量black“。在遍历矩阵之前先将符号外层的0全部标记好(此处用‘ - ’标记)目的是与符号内部的空白洞区分开。 之后就可以用DFS遍历整个图了。遇到1时代表碰到黑点,然后从这个黑点开始遍历图,一旦碰到0(由于象形符号外的0已被标记成”-“,故此时碰到的0必定是象形符号内部的。)说明碰到了空白洞,然后特征量black++,同时将它和所有与它联通的0全部标记成”-“,表示已经遍历过这个洞。然后根据特征量black找到对应的符号储存在一个string类
对象s里。遍历完整幅图后将s进行sort排序后输出即可。
此处从网上题解中习得一个小技巧,在DFS中设一个标志变量isp, isp == 1时用于遍历空白格即0, isp == 2时用于DFS遍历象形符号即黑点。
DFS求连通块的题目,看了好几遍题解才真正弄懂,其实算法并不难,对我而言难的是从题目中读懂题意找到思路,很感谢网上详细明了的题解。
提意简述:给定象形符号的十六制表示方法,找到对应的象形符号,并按字典序递增的顺序输出所有的象形符号。
思路:先将给定的十六进制H*W矩阵先转化成二进制H*(4*W)矩阵,此时0代表空白,1代表黑点(象形符号由1组成)。由于每个象形符号内部含有的空白洞的个数均不相同,所以可以将每个象形符号所含有的空白洞的个数作为与其他符号区别开的”特征量black“。在遍历矩阵之前先将符号外层的0全部标记好(此处用‘ - ’标记)目的是与符号内部的空白洞区分开。 之后就可以用DFS遍历整个图了。遇到1时代表碰到黑点,然后从这个黑点开始遍历图,一旦碰到0(由于象形符号外的0已被标记成”-“,故此时碰到的0必定是象形符号内部的。)说明碰到了空白洞,然后特征量black++,同时将它和所有与它联通的0全部标记成”-“,表示已经遍历过这个洞。然后根据特征量black找到对应的符号储存在一个string类
对象s里。遍历完整幅图后将s进行sort排序后输出即可。
此处从网上题解中习得一个小技巧,在DFS中设一个标志变量isp, isp == 1时用于遍历空白格即0, isp == 2时用于DFS遍历象形符号即黑点。
#include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<set> #include<vector> #include<stack> #include<queue> #include<sstream> #include<cmath> const int maxn = 1100; using namespace std; string ss = "WAKJSD"; string st1, s, st[maxn]; const string stw[16] = {"0000","0001","0010","0011","0100","0101","0110","0111", "1000","1001","1010","1011","1100","1101","1110","1111"}; int h,w,black; void dfs(int r, int c, int isp)//isp为标识符,sp == 1时用于处理空白格0(象形符号外侧和内侧的0均可这么处理) isp == 2时用于遍历每个象形符号 { if(r < 0 || r >= h || c < 0 || c >= 4*w) return; if(isp == 1 && st[r][c] != '0') return; if(isp == 2 && st[r][c] != '0' && st[r][c] != '1') return; if(isp == 1) st[r][c] = '-'; // if(isp == 3) st[r][c] = '-'; if(isp == 2) { if(st[r][c] == '0') { black++;//特征量用于区分不同的象形符号 dfs(r, c, 1); } if(st[r][c] == '1') { st[r][c] = '*'; } } dfs(r-1, c, isp); dfs(r+1, c, isp); dfs(r, c-1, isp); dfs(r, c+1, isp); } //void print() //{ // for(int i = 0; i < h; i++) // { // for(int j = 0; j < 4*w; j++) // { // cout << st[i][j] << " "; // } // cout << endl; // } //} int main() { int kase = 0;; while(~scanf("%d%d",&h,&w)) { if(!h && !w) break; for(int i = 0; i < maxn; i++) st[i].clear(); s.clear(); string str; for(int i = 0; i < h; i++)//十六进制转二进制后储存在t中 { cin >> str; for(int j = 0; j < w; j++) { int t; if(str[j] >= 'a' && str[j] <= 'z') t = str[j] - 'a' + 10; if(str[j] >= '0' && str[j] <= '9') t = str[j] - '0'; st[i] += stw[t]; } } // print(); for(int i =0 ; i < h; i++)//从矩阵左右侧出发处理象形符号外侧的空白格 { if(st[i][0] == '0') dfs(i, 0, 1); if(st[i][4*w-1] == '0') dfs(i, 4*w-1, 1); } for(int j = 0; j < 4*w-1; j++)//从矩阵上下侧出发处理象形符号外侧的空白格 { if(st[0][j] == '0') dfs(0, j, 1); if(st[h-1][j] == '0') dfs(h-1, j, 1); } // print(); for(int i = 0; i < h; i++)//遍历象形符号,统计每个符号含有的空白洞的数目,即特征量。 { for(int j = 0; j < 4*w-1; j++) { if(st[i][j] == '1') { black = 0; dfs(i, j, 2); s += ss[black]; } } } sort(s.begin(), s.end()); printf("Case %d: ",++kase); cout << s << endl; } return 0; }
相关文章推荐
- 渗透技术一瞥(图)
- 图片引发的溢出危机(图)
- C语言进制转换代码分享
- C++实现图的邻接矩阵存储和广度、深度优先遍历实例分析
- C++实现图的邻接表存储和广度优先遍历实例分析
- PHP中实现中文字符进制转换原理分析
- php 实现进制相互转换
- jQuery圆形统计图开发实例
- JS中字符问题(二进制/十进制/十六进制及ASCII码之间的转换)
- php 实现进制转换(二进制、八进制、十六进制)互相转换实现代码
- javascript parseInt() 函数的进制转换注意细节
- 进制转换算法原理(二进制 八进制 十进制 十六进制)
- Shell脚本中不同进制数据转换的例子(二进制、八进制、十六进制、base64)
- 手机短信轰炸(图)
- 使用JavaScript进行进制转换将字符串转换为十进制
- C语言实现图的遍历之深度优先搜索实例
- python数据结构之图的实现方法
- ASP.Net页面生成饼图实例
- Javascript进制转换实例分析
- javascript常见数字进制转换实例分析