1.题目描述:点击打开链接
2.解题思路:本题给出了一张图片的16进制的编码,要求找出这张图片中出现的符号。解码成二进制字符串后,实际上就是用普通的dfs解决了,不过如何进行dfs是本题的关键。
根据题意,每个符号的不同之处在于“洞”的个数不同,这就是它们的特征值,因此只要能够找出每个图形的洞的个数,即可确定图案是谁了。为了能够更好地进行dfs,我们需要先将图案外侧的所有0给标记掉,这里用字符‘-’来处理。然后再扫描这张图,如果遇到字符‘1’,说明找到了一个黑点,从它入手找到整个图案,用‘*’来标记黑点;如果在寻找过程中遇到了‘0’,说明找到了一个洞,对它也进行上述的处理,同时更新找到的洞的个数。
综上所述,我们相当于要进行三种不同的dfs。第一种是用来处理边界;第二种是标记图案的黑点;第三种是统计图案中内部的洞的个数。这里有一个技巧:给dfs传递一个控制变量isp,由它来控制三种不同的类型。具体过程详见代码注释。
由于本题没有给出具体的测试样例,因此以下附上找到的测试数据供测试。
3.代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;
#define N 1024
int H, W, ant, black;
char*ch = "WAKJSD";
string s, res, ans[N];
const char*table[] = { "0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111", "1000", "1001", "1010",
"1011", "1100", "1101", "1110", "1111" };
void clear()
{
for (int i = 0; i < N; i++)
ans[i].clear();
}
void dfs(int r, int c, int isp)//isp为1时标记边界;2标记黑点;3标记所有的洞
{
if (r < 0 || r >= H || c < 0 || c >= W * 4)return;
if ((isp == 1 || isp == 3) && ans[r][c] != '0')return;
if (isp == 2 && ans[r][c] != '1'&&ans[r][c] != '0')return;
if (isp == 1)ans[r][c] = '-';
if (isp == 2 && ans[r][c] == '0')
{
black++;
dfs(r, c, 3);
}
if (isp == 2 && ans[r][c] == '1')
ans[r][c] = '*';
if (isp == 3)ans[r][c] = '-';
dfs(r + 1, c, isp);
dfs(r, c + 1, isp);
dfs(r - 1, c, isp);
dfs(r, c - 1, isp);
}
int main()
{
//freopen("t.txt", "r", stdin);
int rnd = 1;
while (~scanf("%d%d", &H, &W) && (H || W))
{
ant = 0;
res.clear();
clear();
for (int i = 0; i < H; i++)
{
cin >> s;
for (int j = 0; j < W; j++)
{
int t;
if (isdigit(s[j]))
t = s[j] - '0';
else t = 10 + s[j] - 'a';
ans[i] += table[t];
}
}
for (int i = 0; i < H; i++)//处理左右两个边界
{
if (ans[i][0] == '0')dfs(i, 0, 1);
if (ans[i][W * 4 - 1] == '0')dfs(i, W * 4 - 1, 1);
}
for (int i = 0; i < W * 4; i++)//处理上下两个边界
{
if (ans[0][i] == '0')dfs(0, i, 1);
if (ans[H - 1][i] == '0')dfs(H - 1, i, 1);
}
for (int i = 0; i < H;i++)
for (int j = 0; j < W * 4;j++)
if (ans[i][j] == '1')//找到一个符号
{
black = 0;
dfs(i, j, 2);
res += ch[black];
}
sort(res.begin(), res.end());//最后要按照字典序输出
printf("Case %d: ", rnd++);
cout << res << endl;
}
return 0;
}
4.测试数据:
6 2
00
7c
44
7c
30
00
6 25
0000000000000000000000000
0000000000000000000000000
00001fe0000000000007c0000
00003fe0000000000007c0000
0000000000000000000000000
0000000000000000000000000
10 3
000
778
548
748
578
700
000
7f0
1e0
000
16 2
00
7e
42
7e
42
7e
42
7e
42
7e
42
7e
00
00
4a
00
16 1
0
1
2
3
4
5
6
7
8
9
a
b
c
d
e
f
9 2
00
7e
42
7e
42
7e
42
7e
00
43 2
00
7e
00
7e
42
7e
42
7e
42
7e
00
7e
42
7e
00
7e
42
7e
42
7e
00
7e
42
7e
42
7e
42
7e
42
7e
00
7e
42
7e
42
7e
42
7e
42
7e
42
7e
00
200 50
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000