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 }
代码君

 

posted @ 2014-09-24 05:10  AOQNRMGYXLMV  阅读(1171)  评论(0编辑  收藏  举报