【DFS】UVa1103 - Ancient Messages

题意

给H行W列的字符矩阵,每个字符对应一个16位进制的数,转化为二进制后,1表示黑点,0表示白点,表示的文字可拉伸但不可断开,求所给矩阵表示的象形文字。

输出时每个文字对应的缩写如下

Ankh:A

Wedjat:J

Djed:D

Scarab:S

Was:W

Akeht:K

思路

刚开始完全没有思路,后来看别人题解才明白每个文字不同之处在于连通块的数目:A:0,  J:3,  D:5,  S:4,  W:0,  K:2 。

先把每行每个字符转化成二进制后存在tab数组里,之后dfs

为了区别文字内的白块与文字外的白块,需要先将矩阵加一个外围,即从tab[1]开始,且每行从tab[i][1]存储;先DFS1将文字外的0全都赋值为‘*’,再DFS2每个图形里面有几个连通块。

总结

还是不会dfs,看的别人的题解写出来的,改动也不是多大。

目前所总结的dfs写法:先写上退出条件,再找到递归条件,遍历其周围的字符。

现在的状态是题解可以看明白,但是在怎么找到这个DFS的思路方面没有开窍。

TIPS:

1.  map的遍历要有迭代器,用C++11的特性for (auto i : cnt) while (i.second--) cout << i.first;   这样写也可以。注意:用迭代器的时候是it->first。

2.  memcpy

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <map>
 5 #include <cstring>
 6 #include <string>
 7 const int maxn = 205;
 8 using namespace std;
 9 const string dict[16] = {
10     "0000", "0001", "0010", "0011",
11     "0100", "0101", "0110", "0111",
12     "1000", "1001", "1010", "1011",
13     "1100", "1101", "1110", "1111",
14 };
15 const int dir[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
16 const char alp[8] = { 'W', 'A', 'K', 'J', 'S', 'D' };
17 char tab[maxn][maxn];
18 int H, W, kase, cur;
19 
20 bool isin(const int r, const int c)
21 {
22     return r >= 0 && r <= H+1 && c >= 0 && c <= W+1;
23 }
24 void dfs1(const int r, const int c)
25 {
26     if(!isin(r,c) || tab[r][c] != '0') return;
27     tab[r][c] = '*';
28     for(int i = 0; i < 4; i++)
29         dfs1(r+dir[i][0],c+dir[i][1]);
30 }
31 void dfs2(const int r, const int c)
32 {
33     if(!isin(r,c) || tab[r][c] != '1') return;
34     tab[r][c] = '*';
35     for(int i = 0; i < 4; i++) {
36         int dr = r+dir[i][0], dc = c + dir[i][1];
37         if(tab[dr][dc] == '0') {
38             cur++;
39             dfs1(dr,dc);
40         }
41         else dfs2(dr,dc);
42     }
43 }
44 int main()
45 {
46     while (cin >> H >> W && (H || W)) {
47         memset(tab, '0', sizeof(tab));
48         W *= 4;
49         for (int i = 1; i <= H; ++i){
50             string line, res;
51             cin >> line;
52             int len = line.size();
53             for(int i = 0; i < len; i++)
54                 res += dict[line[i] >= 'a' ? (line[i] - 'a' + 10) : (line[i] - '0')];
55             memcpy(tab[i]+1, res.c_str(), W);
56         }
57         dfs1(0,0);
58         map<char, int> cnt;
59         for(int i = 1; i <= H; i++)
60             for(int j = 1; j <= W; j++) {
61                 if(tab[i][j] != '1') continue;
62                 cur = 0;
63                 dfs2(i,j);
64                 cnt[alp[cur]]++;
65             }
66         cout << "Case " << ++kase << ": ";
67         map<char, int>::iterator it;
68         for(it = cnt.begin(); it != cnt.end(); it++)
69             while(it->second--)
70                 cout << it->first;
71         cout << endl;
72     }
73     return 0;
74 }

 

转载于:https://www.cnblogs.com/kikii233/p/5912752.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值