每组数据包含一个H行W列的字符矩阵(H≤200,W≤50),每个字符为4个相邻像素点的十六进制(例如,10011100对应的字就是9c)。转化为二进制后1表示黑点,0表示白点。输入满足:
- 不会出现上述6种符号之外的其他符号。
- 输入至少包含一个符号,且每个黑像素都属于一个符号。
- 每个符号都是一个四连块,并且不同符号不会相互接触,也不会相互包含。
- 如果两个黑像素有公共顶点,则它们一定有一个相同的相邻黑像素(有公共边)。
- 符号的形状一定和表中的图形拓扑等价(可以随意拉伸但不能拉断)。
Ankh: A,Wedjat: J,Djed: D,Scarab: S,Was: W,Akhet: K
要求按照字典序输出所有符号。
思路:表中6个符号从左至右依次有1(A),3(J),5(D),4(S),0(W),2(K)个圈,各不相同。所以判断圈的个数即可。
以下列数据演示:
10 3
000
778
548
748
578
700
000
7f0
1e0
000
实现方法:
1. 黑色块包裹的圈内白色块肯定不会四连块连接到边缘的块去,所以遍历4条边,并且标记这些非圈内白块。(如图)
2. 开始遍历找黑块,找到一个后进入dfs标记连通块,由题意,一个黑色块最终能标记一整个符号。
继续找黑色块,如果还有,那就是第二个符号,依次类推,同时给符号的标记做区分处理,顺便记录符号个数。
3. 找白色块,此时找到的都是圈内的,找到第一个就dfs标记所有该圈内的白色块(用-2)。
此时判断白色块属于哪个符号:如第一个白色块坐标为(x,y),那么(x-1,y)肯定是黑色块,因为经过了这个黑色块才能进圈。
4. 字典序输出结果。
#include <bits/stdc++.h>
using namespace std;
int pic[200][200], ascii[6]={87,65,75,74,83,68},H, W,n = 0,
t[16][4] = {{0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 1, 0}, {0, 0, 1, 1},
{0, 1, 0, 0}, {0, 1, 0, 1}, {0, 1, 1, 0}, {0, 1, 1, 1},
{1, 0, 0, 0}, {1, 0, 0, 1}, {1, 0, 1, 0}, {1, 0, 1, 1},
{1, 1, 0, 0}, {1, 1, 0, 1}, {1, 1, 1, 0}, {1, 1, 1, 1}};
void filled()//输入图
{
char temp;
for (int i = 0; i < H; i++)
for (int k = 0, c = 0; k < W; k++)
{
scanf(" %c", &temp); //空格吸收回车,字符串读入
if (temp > 96) temp -= 87; //97为a
else temp -= 48;
for (int f = 0; f < 4; f++) //输入的转为4个二进制
pic[i][c++] = t[temp][f]; //c为当前行第几个,换行时清零
}
}
void dfs(int y, int x, int f, int a) //y行 x列 f需要标记的值 a要连通的格子类型
{
if (x >= 4 * W || x < 0 || y >= H || y < 0 || pic[y][x] != a) return; //出界OR不是要爬的格子
pic[y][x] = f; //标记当前格为f
dfs(y - 1, x, f, a);
dfs(y + 1, x, f, a);
dfs(y, x - 1, f, a);
dfs(y, x + 1, f, a);
}
int main()
{
while (cin >> H >> W) //H行 W列
{
if (H == 0)
break; //结束条件0 0
filled();
cout << "Case " << ++n << ": ";
int n = 4, c[100] = {0},cnt=0; //c数组存放符号n的圈的个数
for (int i = 0; i < H; i++) //功能:遍历四条边的每一点
{
int q = 4 * W;
if (i == 0 || i == H - 1) q = 2;
for (int j = 0; j < 4 * W; j += q - 1)
dfs(i, j, -1, 0);
}
for (int i = 0; i < H; i++) //功能:标记每个黑块组成的符号
for (int j = 0; j < 4 * W; j++)
if (pic[i][j] == 1)
dfs(i, j, n++, 1); //防止混淆,n初始为4,当前符号标记为4
for (int i = 0; i < H; i++) //功能:找白块
for (int j = 0; j < 4 * W; j++)
if (pic[i][j] == 0)
{
c[pic[i][j - 1]]++; //直接找前一个黑块的值作为该符号的号码,表示增加一个圈
dfs(i, j, -2, 0); //用-2标记已经计算过的圈内白块
}
for (int i = 4; i < n; i++) c[i]=ascii[c[i]]; //将值换成ASCII码存放
sort(c+4,c+n);//对c数组第4个到第n-1个升序排序
for (int i = 4; i < n; i++) printf("%c",c[i]); //字典序输出 n初始是从4开始算
cout << endl;
}
return 0;
}
原文地址:https://www.cnblogs.com/linme/p/11978278.html
时间: 2024-10-08 15:12:15