anci

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 six hieroglyphs and their names. In this problem, you will write a program to recognize these six characters.
为了理解早期文化,考古学家经常研究古代文字。埃及一种超过3000年的语言,就是基于一些符号,我们称之为象形文字。下图显示了六种象形文字及它们的名字。你需要写出一个程序去识别这六种象形文字。
这里写图片描述
Input :
The input consists of several test cases, each of which describes an image containing one or more hieroglyphs chosen from among those shown in Figure C.1. The image is given in the form of a series of horizontal scan lines consisting of black pixels (represented by 1) and white pixels (represented by 0). In the input data, each scan line is encoded in hexadecimal notation. For example, the sequence of eight pixels 10011100 (one black pixel, followed by two white pixels, and so on) would be represented in hexadecimal notation as 9c. Only digits and lowercase letters a through f are used in the hexadecimal encoding. The first line of each test case contains two integers, H and W. H (0 < H ≤ 200) is the number of scan lines in the image. W (0 < W ≤ 50) is the number of hexadecimal characters in each line. The next H lines contain the hexadecimal characters of the image, working from top to bottom. Input images conform to the following rules:
输入:
输入包含多组测试,每组测试都描述了一张包含一个或多个象形字的图,这些象形文字都是从上面六个象形文字中选出的。这张图由多行水平扫描线组成,包含黑色的像素点(由1表示)和白色的像素点(由0表示)。输入数据中,每行扫描线都是由十六进制数构成。例如,十六进制9c就是一个八个像素点的序列(黑白白黑黑黑白白).输入的十六进制数字和小写字母。每组数据的首行包含两个整数,H和W。H(0 < H ≤ 200)是图中扫描线的行数,W(0 < W ≤50)是每行中十六进制个数。输入的图片保证遵循这个规则。

这张图只包含上图中的六个象形文字。

每个图片包含至少一个有效象形文字。

在图中每个黑色的像素点是有效象形文字的一部分。

每个十六进制有一系列黑白像素点组成,并且每个黑色像素点都有至少一个其他黑色像素点在它的上面,下面,左面或者右面。

这些象形字不会相互接触,并且也不会相互包含。

如果两个黑色像素点角线连接,那么肯定是有一个公共的黑色像素点。

这个象形文字也许会被扭曲,但是形状依然与图中的象形文字拓扑的相等。

输出:
对于每组数据,用以下英文表达出十六进制数所描述的图片中包含的象形文字。

Ankh: A
Wedjat: J
Djed: D
Scarab: S
Was: W
Akhet: K

样例:
3 2
7c
7c
00
Case 1: W

5 3
fff
f0f
fff
f0f
fff
Case 1: K

TJ:
这里写图片描述
像上图中显示的是AKW.

由于图中说的是可以扭曲,那么我们直接来做就不合适,因此要找一个特征值,固定不变的去判断应该是哪个象形文字。
通过观察可以看出很有意思的是每个象形文字中所包含封闭区间是不一样的,A,J,D,S,W,K分别对应的封闭区间为:1,3,5,4,0,2.
那么我们用搜索将0和1变成-1,统计封闭区间的个数即可判断是什么象形文字。

CODE:(转载代码,出处forget)

#include<cstdio>  
#include<cstring>  
#include<iostream>  
#include<algorithm>  
using namespace std;  

int n,m,cnt;  
const int maxn = 210;  
int g[maxn][maxn];  
int num[6];  
char st[6] = {'A', 'D', 'J', 'K', 'S', 'W'};  
char str[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};  
int s[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}  
};  

bool is_in(int x,int y)  
{  
    if(x>=0&&x<=n+1&&y>=0&&y<=m+1)  
        return true;  
    else return false;  
}  

void dfs(int x,int y)  
{  
    if(!is_in(x,y)||g[x][y]!=0)  
        return;  
    g[x][y]=-1;  
    dfs(x-1,y);  
    dfs(x+1,y);  
    dfs(x,y-1);  
    dfs(x,y+1);  
}  
void dfs2(int x,int y)  
{  
    if(!is_in(x,y)||g[x][y]==-1)  
        return;  
    if(g[x][y]==0)  
    {  
        cnt++;  
        dfs(x,y);  
        return;  
    }  
    g[x][y]=-1;  
    dfs2(x-1,y);  
    dfs2(x+1,y);  
    dfs2(x,y-1);  
    dfs2(x,y+1);  
}  

int main()  
{  
    int kase=0;  
    while(scanf("%d%d",&n,&m)!=EOF)  
    {  
        if(n==0&&m==0) break;  
        kase++;  
        memset(g, 0, sizeof(g));  
        memset(num, 0, sizeof(num));  
        for(int i=1;i<=n;i++)  
        {  
            getchar();  
            char ch;  
            int len=1;  
            for(int j=0;j<m;j++)  
            {  
                scanf("%c",&ch);  
                for(int k=0;k<16;k++)  
                {  
                    if(ch==str[k])  
                    {  
                        for(int l=0;l<4;l++)  
                            g[i][len++]=s[k][l];  
                        break;  
                    }  
                }  
            }  
        }  
        m=m*4;  
        dfs(0,0);  
        for(int i=0;i<n;i++)  
        {  
            for(int j=0;j<m;j++)  
            {  
                if(g[i][j]==1)  
                {  
                    cnt=0;  
                    dfs2(i,j);  
                    if(cnt==0) num[5]++;  
                    if(cnt==1) num[0]++;  
                    if(cnt==2) num[3]++;  
                    if(cnt==3) num[2]++;  
                    if(cnt==4) num[4]++;  
                    if(cnt==5) num[1]++;  
                }  
            }  
        }  
        printf("Case %d: ",kase);  
        for(int i=0;i<6;i++)  
        {  
            printf(" %d ",num[i]);  
            while(num[i]--)  
            {  
                printf("%c",st[i]);  
            }  
        }  
        printf("\n");  
    }  
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值