UVa 1103 (利用连通块来判断字符) Ancient Messages

本题就是灵活运用DFS来求连通块来求解的。

题意:

给出一幅黑白图像,每行相邻的四个点压缩成一个十六进制的字符。然后还有题中图示的6中古老的字符,按字母表顺序输出这些字符的标号。

分析:

首先图像是被压缩过的,所以我们要把它解码成一个01矩阵。而且我们还要在原图像的四周加一圈白边,这样图中的白色背景都连通起来了。

黑色连通块的个数就是字符的个数。

观察题中字符样式可知,每种字符中包裹的“白洞”的个数是不同的,所以我们可以根据每个字符中的“白洞”的个数来区别这些字符。

然后我们给所有的连通块染色,并用color存储所标记的颜色。第一个染的是白色背景色,编号为1

把所有的黑色连通块的标号存放到cc里面

neighbors是由若干个集合所组成的数组,记录的是黑色连通块i周围相连的非背景色的白块,即“白洞”。

最后每个集合中元素的个数对应的就是字符的编号,最后排序输出即可。

一个DEBUG很久的低级错误:在DFS的时候忘了加 color[row2][col2] == 0 这一判断条件,相当于没有回溯了,当然会栈溢出,RE。这里的color顺带也起到了表示是否访问过的作用。

  1 //#define LOCAL
  2 #include <algorithm>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <vector>
  6 #include <set>
  7 using namespace std;
  8
  9 const int maxl = 200 + 5;
 10 char bin[256][5], s[maxl];
 11 const int dr[] = { 1, 0, -1, 0 };
 12 const int dc[] = { 0, 1, 0, -1 };
 13 int picture[maxl][maxl], color[maxl][maxl], w, h;
 14
 15 vector<set<int> > neighbor;
 16
 17 void decode(int row, int col, char c)
 18 {
 19     for(int i = 0; i < 4; ++i)
 20         picture[row][col + i] = bin[c][i] - ‘0‘;
 21 }
 22
 23 bool inside(int row, int col)
 24 {
 25     return row>=0 && row<h && col>=0 && col<w;
 26 }
 27
 28 void DFS(int row, int col, int c)
 29 {
 30     color[row][col] = c;
 31     for(int i = 0; i < 4; ++i)
 32     {
 33         int row2 = row + dr[i];
 34         int col2 = col + dc[i];
 35         if(inside(row2, col2) && picture[row][col] == picture[row2][col2] && color[row2][col2] == 0)
 36             DFS(row2, col2, c);
 37     }
 38 }
 39
 40 void check_neighbor(int row, int col)
 41 {
 42     for(int i = 0; i < 4; ++i)
 43     {
 44         int row2 = row + dr[i];
 45         int col2 = col + dc[i];
 46         if(row2>=0 && row2<h && col2>=0 && col2<w && picture[row2][col2] == 0 && color[row2][col2] != 1)//寻找"洞"
 47             neighbor[color[row][col]].insert(color[row2][col2]);
 48     }
 49 }
 50
 51 const char* code = "WAKJSD";
 52
 53 char recgonize(int c)
 54 {
 55     int a = neighbor[c].size();
 56     return code[a];
 57 }
 58
 59 int main(void)
 60 {
 61     #ifdef LOCAL
 62         freopen("1103in.txt", "r", stdin);
 63     #endif
 64
 65     strcpy(bin[‘0‘], "0000");
 66     strcpy(bin[‘1‘], "0001");
 67     strcpy(bin[‘2‘], "0010");
 68     strcpy(bin[‘3‘], "0011");
 69     strcpy(bin[‘4‘], "0100");
 70     strcpy(bin[‘5‘], "0101");
 71     strcpy(bin[‘6‘], "0110");
 72     strcpy(bin[‘7‘], "0111");
 73     strcpy(bin[‘8‘], "1000");
 74     strcpy(bin[‘9‘], "1001");
 75     strcpy(bin[‘a‘], "1010");
 76     strcpy(bin[‘b‘], "1011");
 77     strcpy(bin[‘c‘], "1100");
 78     strcpy(bin[‘d‘], "1101");
 79     strcpy(bin[‘e‘], "1110");
 80     strcpy(bin[‘f‘], "1111");
 81
 82     int kase = 0;
 83     while(scanf("%d%d", &h, &w) == 2 && h)
 84     {
 85         memset(picture, 0, sizeof(picture));
 86         for(int i = 0; i < h; ++i)
 87         {
 88             scanf("%s", s);
 89             for(int j = 0; j < w; ++j)
 90                 decode(i+1, j*4+1, s[j]);
 91         }
 92
 93         h += 2;
 94         w = w * 4 + 2;
 95
 96         int cnt = 0;
 97         vector<int> cc;
 98         memset(color, 0, sizeof(color));
 99         for(int i = 0; i < h; ++i)
100             for(int j = 0; j < w; ++j)
101                 if(!color[i][j])
102                 {
103                     DFS(i, j, ++cnt);
104                     if(picture[i][j] == 1)    cc.push_back(cnt);
105                 }
106
107         neighbor.clear();
108         neighbor.resize(cnt + 1);
109         for(int i = 0; i < h; ++i)
110             for(int j = 0; j < w; ++j)
111                 if(picture[i][j] == 1)
112                     check_neighbor(i, j);
113
114         vector<char> ans;
115         for(int i = 0; i < cc.size(); ++i)
116             ans.push_back(recgonize(cc[i]));
117         sort(ans.begin(), ans.end());
118
119         printf("Case %d: ", ++kase);
120         for(int i = 0; i < ans.size(); ++i)    printf("%c", ans[i]);
121         printf("\n");
122     }
123
124     return 0;
125 }

代码君

时间: 2024-11-08 01:40:08

UVa 1103 (利用连通块来判断字符) Ancient Messages的相关文章

UVA 572 油田连通块-并查集解决

题意:8个方向如果能够连成一块就算是一个连通块,求一共有几个连通块. 分析:网上的题解一般都是dfs,但是今天发现并查集也可以解决,为了方便我自己理解大神的模板,便尝试解这道题目,没想到过了... 1 #include <cstdio> 2 #include <iostream> 3 #include <sstream> 4 #include <cmath> 5 #include <cstring> 6 #include <cstdlib&

图-用DFS求连通块 UVa 1103

这道题目甚长, 代码也是甚长, 但是思路却不是太难.然而有好多代码实现的细节, 确是十分的巧妙. 对代码阅读能力, 代码理解能力, 代码实现能力, 代码实现技巧, DFS方法都大有裨益, 敬请有兴趣者耐心细读.(也许由于博主太弱, 才有此等感觉). 题目: UVa 1103 In order to understand early civilizations, archaeologists often study texts written in  ancient languages. One

UVA 572 Oil Deposits油田(DFS求连通块)

UVA 572     DFS(floodfill)  用DFS求连通块 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M

UVa 572 油田(DFS求连通块)

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=513 终于开始接触图了,恩,开始接触DFS了,这道题就是求连通分量,比较简单. 1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 5 int m, n; //记录连通块的数量 6 cha

UVA 572 -- Oil Deposits(DFS求连通块+种子填充算法)

UVA 572 -- Oil Deposits(DFS求连通块) 图也有DFS和BFS遍历,由于DFS更好写,所以一般用DFS寻找连通块. 下述代码用一个二重循环来找到当前格子的相邻8个格子,也可用常量数组或者写8条DFS调用. 下述算法是:种子填充(floodfill) 两种连通区域 四连通区域:从区域内一点出发,可通过上.下.左.右四个方向的移动组合,在不越出区域的前提下,能到达区域内的任意像素 八连通区域:从区域内每一像素出发,可通过八个方向,即上.下.左.右.左上.右上.左下.右下移动的

Ancient Messages UVA - 1103

题目链接:https://vjudge.net/problem/UVA-1103 题目大意:每组数据包含H行W列的字符矩阵(H<=200,W<=50) 每个字符为为16进制  你需要把它转化为二进制.  转化为二进制之后 1代表黑点 0代表白点 问你出现的所有符号  并按字典序输出! 思路:首先看到这道题,完全没看懂题意 ,真的没看懂,后来搜了题解才看明白题意,但是还是不会做,这道题是在紫书上看到的,紫书上并没有给出代码,学了别人的博客! 好了  具体怎么做呢? 仔细观察可以发现,每个字符中出

uva 11853 Paintball dfs找连通块

题意: 给出一个矩形湖, 湖里面有一些圆形地小岛, 问能否从左岸乘船到达右岸,如果能,找出最上面的起点和终点. 题解: 如果能从左岸到达右岸,那么一定不能存在一个连通的岛屿从上岸连到下岸, 所以直接从上到下做dfs,判断是否存在从上岸到下岸地连通块,完成判断.那么接下来就是如何找出最上方地点了,画画图便发现,对于起点,如果存在跨越上岸和左岸地连通岛屿,那么起点一定只能在左岸地交点下方,所以,只需在dfs的过程中更新起点和终点位置即可. 代码: #include <queue> #include

UVA 572 dfs求连通块

The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyze

UVa 572 Oil Deposits(DFS求8连通块)

题意  求n*m矩阵中'@'连通块的个数  两个'@'在一个九宫格内就属于一个连通块 最基础的DFS  遇到@就递归扫描周围8个并标记当前格子已访问  然后就得到答案了 #include<cstdio> using namespace std; const int N = 110; char mat[N][N]; int dfs(int r, int c) { if(mat[r][c] != '@') return 0; else { mat[r][c] = '*'; for(int i =