uva1103 古代象形符号

给出一幅黑白图像,每行相邻的四个点压缩成一个十六进制的字符。然后还有题中图示的6中古老的字符,按字母表顺序输出这些字符的标号。

输出说明:
For each test case, display its case number followed by a string containing one character for each
hieroglyph recognized in the image, using the following code:
Ankh: A
Wedjat: J
Djed: D
Scarab: S
Was: W
Akhet: K

 

 

题目本身的意思很奇怪,我们要解决这个问题就必须要把象形文字的状态用其他形式设计出来。在本题中,经过观察可以发现六个不同的字母图形,

他们的区别在于内部的白洞数量各不相同,所以我们可以用每个字母内部的白的联通块的求出来,这样我们也就知道了每个字母的个数,我们只需要

使用floodfill统计即可。解决了第一个问题,我们还要面对的一个问题就是如何把输入改写成我们可以看懂的部分,这里涉及的问题主要是十六进制转

二进制。这里的转换过程直接用2个数组来完成。

 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;
                    }
                }
            }
        }

之后问题就转化为了一个简单的floodfill的过程,需要注意要提前把图片外围一周先做标记。

具体代码如下

#include<bits/stdc++.h>
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)//将字外围空白部分-1化,缩小化字出现的地方
        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++)
        {
            while(num[i]--)
            {
                printf("%c",st[i]);
            }
        }
        printf("\n");
    }
}

 

posted @ 2020-09-24 10:31  徒手拆机甲  阅读(285)  评论(0)    收藏  举报