一道DFS的题
首先需要将给的16进制数字字符转换为2进制数字字符
个人花费时间较多地方是 如何将多个文字所对应的空洞数与该文字对应上
这里给出一种方法,当然很多大神的题解也写过此方法
1.先给图像数组外围加一圈0,这是为了保证非文字包含的‘0’(背景‘0’),能构成连通块,以方便用dfs给它特异化掉,我是将‘0’换成‘x’
2.遍历图像,一旦找到‘1’(找到某1个文字),就就利用DFS抹掉这个连通块(文字),并在该DFS过程中遇到‘0'时,再另外用一个DFS抹掉文字中的空洞连通块,并计数
3.最后根据得到的空洞数,就可得到对应的输出字符,排序输出即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
#define MAXINDEX 110
#define MAXROW 805
#define MAXCOL 205
char* num_map[MAXINDEX];
char image[MAXROW][MAXCOL];
int dr[] = { -1,1,0,0 };
int dc[] = { 0,0,-1,1 };
char code[] = { 'W','A','K','J','S','D' };
int row, col;
string buf;
void init_map()//构建16进制与2进制编码映射
{
num_map['0'] = "0000";
num_map['1'] = "0001";
num_map['2'] = "0010";
num_map['3'] = "0011";
num_map['4'] = "0100";
num_map['5'] = "0101";
num_map['6'] = "0110";
num_map['7'] = "0111";
num_map['8'] = "1000";
num_map['9'] = "1001";
num_map['a'] = "1010";
num_map['b'] = "1011";
num_map['c'] = "1100";
num_map['d'] = "1101";
num_map['e'] = "1110";
num_map['f'] = "1111";
}
class _pair
{
public:
int _r;
int _c;
_pair(int r, int c) :_r(r), _c(c){}
_pair next(int dir) const
{
return _pair(this->_r + dr[dir], this->_c + dc[dir]);
}
};
bool is_inside(const _pair &pair)//在图像外围加了一圈0(右边和下边),使得非文字的背景0能构成连通块,因此限制范围加1即可
{
return pair._r >= 0 && pair._r <= row + 1 && pair._c >= 0 && pair._c <= 4 * col + 1;
}
void dfs_background(const _pair &start)
{
stack<_pair> _stack;
_stack.push(start);
while (!_stack.empty())
{
_pair cur = _stack.top();
_stack.pop();
image[cur._r][cur._c] = 'x';//将文字背景特征化
for (int i = 0;i != 4;++i)
{
_pair next = cur.next(i);
if (is_inside(next) && image[next._r][next._c] == '0')
{
_stack.push(next);
}
}
}
}
void dfs_word(const _pair &start, int &count)
{
bool flag = false;
stack<_pair> _stack;
_stack.push(start);
while (!_stack.empty())
{
_pair cur = _stack.top();
_stack.pop();
image[cur._r][cur._c] = 'x';//文字中的空洞标记为已访问
for (int i = 0;i != 4;++i)
{
_pair next = cur.next(i);
if (is_inside(next) && image[next._r][next._c] == '0')
{
_stack.push(next);
flag = true;//标记为发现空洞
}
}
}
if (flag)
{
++count;
}
}
void dfs(const _pair &start, int &count)
{
stack<_pair> _stack;
_stack.push(start);
while (!_stack.empty())
{
_pair cur = _stack.top();
image[cur._r][cur._c] = 'x';
_stack.pop();
for (int i = 0;i != 4;++i)
{
_pair next = cur.next(i);
if (is_inside(next) && image[next._r][next._c] == '1')
{
dfs_word(next, count);
_stack.push(next);
}
}
}
}
void init_decode()//在图像外围加了一圈0(左边和上边),使得非文字的背景0能构成连通块
{
for (int i = 0;i != row;++i)
{
cin >> buf;
for (int j = 0;j != col;++j)
{
image[i + 1][4 * j + 1] = num_map[buf[j]][0];
image[i + 1][4 * j + 2] = num_map[buf[j]][1];
image[i + 1][4 * j + 3] = num_map[buf[j]][2];
image[i + 1][4 * j + 4] = num_map[buf[j]][3];
}
}
}
int main()
{
int n = 0;
init_map();
while (1)
{
memset(image, '0', sizeof(image));
cin >> row >> col;
if (!row && !col)
{
break;
}
int colsum = 4 * col;
++n;
init_decode();
dfs_background(_pair(0, 0));
string codes;
for (int i = 0;i != row;++i)
{
for (int j = 0;j != colsum;++j)
{
if (image[i][j] == '1')
{
int cnt = 0;
dfs(_pair(i, j), cnt);
codes += code[cnt];
}
}
}
sort(codes.begin(), codes.end());
printf("Case %d: %s\n", n, codes.c_str());
}
return 0;
}
虽说是非递归的DFS,但是速度不是很快,在UVA上是0.049s,我找了一个递归的DFS,速度0.019,相比慢了很多。
理论来说非递归要比递归要快一些,可能是因为构造函数拖慢了速度。
如果有大神知道哪里是速度瓶颈,请多多指教