UVA 1103

来源:互联网 发布:封神传奇知乎 编辑:程序博客网 时间:2024/04/30 15:25

一道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 205char* 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,相比慢了很多。

理论来说非递归要比递归要快一些,可能是因为构造函数拖慢了速度。

如果有大神知道哪里是速度瓶颈,请多多指教



0 0