UVA1103 Ancient Messages 题解

每组数据包含一个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

UVA1103 Ancient Messages 题解的相关文章

Uva1103 Ancient Messages

题意:识别图中的象形文字.但是,图形可以任意的拉伸,但不能拉断. 分析:这种题如果图形没有特征是不可做类型的题,不过观察图形可以发现每个图形中的洞的数量是一定的,我们只需要数出每一个封闭图形的洞数就能知道这是哪个图形. 虽然知道了原理,但是并不是特别好做,首先我们需要一次dfs将所有图形旁边的点全都变为"不可访问",然后从每个黑点开始枚举,向四周扩展,遇到白色的块就用第一次的dfs函数覆盖,否则继续第二次dfs,两次dfs交错使用,思路比较巧妙. #include <cstdio

K - Ancient Messages(dfs求联通块)

K - Ancient Messages Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVA 1103 Appoint description: Description In order to understand early civilizations, archaeologists often study texts written in ancie

Ancient Messages UVA - 1103

题目链接:https://vjudge.net/problem/UVA-1103 题目大意:每组数据包含H行W列的字符矩阵(H<=200,W<=50) 每个字符为为16进制  你需要把它转化为二进制.  转化为二进制之后 1代表黑点 0代表白点 问你出现的所有符号  并按字典序输出! 思路:首先看到这道题,完全没看懂题意 ,真的没看懂,后来搜了题解才看明白题意,但是还是不会做,这道题是在紫书上看到的,紫书上并没有给出代码,学了别人的博客! 好了  具体怎么做呢? 仔细观察可以发现,每个字符中出

UVa 1103 (利用连通块来判断字符) Ancient Messages

本题就是灵活运用DFS来求连通块来求解的. 题意: 给出一幅黑白图像,每行相邻的四个点压缩成一个十六进制的字符.然后还有题中图示的6中古老的字符,按字母表顺序输出这些字符的标号. 分析: 首先图像是被压缩过的,所以我们要把它解码成一个01矩阵.而且我们还要在原图像的四周加一圈白边,这样图中的白色背景都连通起来了. 黑色连通块的个数就是字符的个数. 观察题中字符样式可知,每种字符中包裹的“白洞”的个数是不同的,所以我们可以根据每个字符中的“白洞”的个数来区别这些字符. 然后我们给所有的连通块染色,

UVA 1103 Ancient Messages (DFS)

起初学习dfs的时候 看不懂这个题目  回过头来今天看的时候思路相对比较清晰了.但还是想不到怎么处理 查询有多少个空白洞.并且一个图中还有好多个象形字符.网上思路是 在周围扩展一圈0,使得文字之外的所有0 都连通,一次dfs标记所有文字之外的0为-1.然后遍历图,发现1就沿着有1 的路径dfs2,在这个过程中,如果发现0,那么必然是文字内部的空洞,此时把空洞dfs 置为-1,标记以后不再走.那么发现几次0就有几个空洞在文字中.那么每一次的dfs2,就处理了一个象形文字.cnt的值就是空洞的个数即

uva 1103 - Ancient Messages(象!形!文!字! dfs遍历计数)

我今天做的这叫什么题-- 今天这个题直接跪了,一看十六进制直接懵了.. 然后在csdn上竟然发现了身边直系学长写的解题报告,然后问了一下解题的思路.然后写出来的代码,想要测试数据吗吧哈哈 给一组最基本的~ 5 3 fff f0f fff f0f fff 输出应该是K AC代码如下: #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace

LRJ-Example-06-13-Uva1103

pic[][]数组存储每个点的值,0或1,输入时在原图的周围加了一圈0. color[][]数组存储每个点的color值,从1开始,dfs(row, col, c) 负责对每个点着色,连通在一起的连通块的颜色相同. 因为最先着色的是最外围的白色点,即background white,这些点的color值是1. neighbour[]数组的下标是color值,内容是一个set,存储下标color所代表的连通块周围的连通块的颜色,background white这个连通块不算. 比如 1. 测试用例

UVA - 1103Ancient Messages(dfs)

UVA - 1103Ancient Messages In order to understand early civilizations, archaeologists often study texts written in ancient languages.One such language, used in Egypt more than 3000 years ago, is based on characters called hieroglyphs.Figure C.1 shows

poj 2159 D - Ancient Cipher 文件加密

Ancient Cipher Description Ancient Roman empire had a strong government system with various departments, including a secret service department. Important documents were sent between provinces and the capital in encrypted form to prevent eavesdropping