• Ancient Messages UVA


    题目链接:https://vjudge.net/problem/UVA-1103

     题目大意:每组数据包含H行W列的字符矩阵(H<=200,W<=50) 每个字符为为16进制  你需要把它转化为二进制。  转化为二进制之后 1代表黑点 0代表白点

    问你出现的所有符号  并按字典序输出!

    思路:首先看到这道题,完全没看懂题意 ,真的没看懂,后来搜了题解才看明白题意,但是还是不会做,这道题是在紫书上看到的,紫书上并没有给出代码,学了别人的博客!

    好了  具体怎么做呢? 

    仔细观察可以发现,每个字符中出现的圆是不一样的,看一道题,很多时候就是找特征量,用特征量来区分题目中的量! 这题的特征量就是每个字符中圆的个数了!  读者仔细看一下图就能明白了

    然后我们知道了特征量是圆 所以我们求得该图形有多少个圆是不是就知道了是哪个图形呢?  当然是的

    但是问题来了,怎么求得图形内有多少个圆呢?  我也想了很久 ,这个到底怎么控制,首先你得知道那些白点是不是构成圆,而且这些圆还要在黑色像素之内。  感觉完全没有思路呀 

    注意题目中说了,两个图形并不会相接触,这就很重要了,不会相接触,那么我们想一下,当我们知道了一条黑色曲线,是不是与它相接触的白点就是圆环?  有人可能会说,不一定吧  也可能不构成圆环啊

    是的 ,的确有可能,不构成圆环的话肯定是最外围的那一些白色点,我们把这些点连成一个连通块,考虑情况的时候把它忽略就行了。   所以要解决这道题的关键就是分析上面内容了

    其他的就是求连通块,注意黑色连通块要存起来,因为我们是通过黑色连通块来寻找有多少个白色圆环的   到这这道题就解决了

    看代码:

    #include<iostream>
    #include<vector>
    #include<set>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    const int maxh=200+5;
    const int maxw=50*4+5;
    char bin[256][5];
    int H,W,pic[maxh][maxw],color[maxh][maxw];
    char line[maxw];
    //pic[i][j]  i j 从1开始
    void decode(char ch,int row,int col)
    {
        for(int i=0;i<4;i++)
        {
            pic[row][col+i]=bin[ch][i]-'0';
        }
    }
    const int dr[]={-1,1,0,0};
    const int dc[]={0,0,-1,1};
    void dfs(int row,int col,int c)//把属于一个连通块的归为一个color值
    {
        color[row][col]=c;//该位置标记为访问过
        for(int i=0;i<4;i++)
        {
            int row2=row+dr[i];
            int col2=col+dc[i];
            //是否为合法的位置
            if(row2>=0&&row2<H&&col2>=0&&col2<W&&pic[row2][col2]==pic[row][col]&&color[row2][col2]==0)//是否为相等的元素
            {
                dfs(row2,col2,c);
            }
        }
    }
    
    vector<set<int> >neighbors;
    
    //这里set集合的确用的好  这样就不会有重复的白色块了 !!!
    void check_neighbors(int row,int col)
    {
        for(int i=0;i<4;i++)
        {
            int row2=row+dr[i];
            int col2=col+dc[i];//color 为1 代表是最外围的白色部分  并不是圈
            if(row2>=0&&row2<H&&col2>=0&&col2<W&& pic[row2][col2]==0&&color[row2][col2]!=1)
                neighbors[color[row][col]].insert(color[row2][col2]);
        }
    }
    
    /*
    
    Ankh: A   1个
    Wedjat: J 3个
    Djed: D   5个
    Scarab: S 4个
    Was: W    0个
    Akhet: K  2个
    
    */
    
    const char* code="WAKJSD";//以有多少个圈来排序   刚好是012345个
    //以容器长度来表示黑连通块旁的内白连通块数
    char recognize(int c)
    {
        int cnt=neighbors[c].size();//该黑色连通块有周围有多少个白圈
        return code[cnt];
    }
    
    int main()
    {
        strcpy(bin['0'],"0000");//这里相当于bin[i]  i是字符1的ascii码
        strcpy(bin['1'],"0001");
        strcpy(bin['2'],"0010");
        strcpy(bin['3'],"0011");
        strcpy(bin['4'],"0100");
        strcpy(bin['5'],"0101");
        strcpy(bin['6'],"0110");
        strcpy(bin['7'],"0111");
        strcpy(bin['8'],"1000");
        strcpy(bin['9'],"1001");
        strcpy(bin['a'],"1010");
        strcpy(bin['b'],"1011");
        strcpy(bin['c'],"1100");
        strcpy(bin['d'],"1101");
        strcpy(bin['e'],"1110");
        strcpy(bin['f'],"1111");
        int ca=0;
        while(cin>>H>>W)
        {
            if(H==0&&W==0) break;
            memset(pic,0,sizeof(pic));
            for(int i=0;i<H;i++)
            {
                scanf("%s",line);
                for(int j=0;j<W;j++)
                {
                    decode(line[j],i+1,j*4+1);//转换为对应的二进制
                }
            }
            H+=2;//这两步是为何  为何要加2???难道是把原来的包围起来???
            W=W*4+2;//是的  如果不这样的话 不能保证最外围的白色一定是1
    
            int cnt=0;//存有多少个连通块
            vector<int> cc;//存所有黑色连通块
            memset(color,0,sizeof(color));//标记数组
            for(int i=0;i<H;i++)
            {
                for(int j=0;j<W;j++)
                {
                    if(!color[i][j])//没有标记过
                    {
                        dfs(i,j,++cnt);
                        if(pic[i][j]==1) cc.push_back(cnt);//扫描矩阵 且为所有连通块编号  并把黑连通块存进cc容器中
    
    
                    }
                }
            }
            neighbors.clear();
            neighbors.resize(cnt+1);//设置容器大小  原来这步是不能少的  !!  少了的话 neighbors[i]  就出错了!!  切记!!
            for(int i=0;i<H;i++)//再扫描一遍??
            {
                for(int j=0;j<W;j++)
                {
                    if(pic[i][j]==1)
                        check_neighbors(i,j);//扫描黑点 并把该点旁边有几个内连通白块存入neighbors容器  其实下标为黑点对应的连通块编号
                }
            }
            vector<char>ans;
            for(int i=0;i<cc.size();i++)//遍历所有的黑色连通块
                ans.push_back(recognize(cc[i]));//存目标值 并排序
            sort(ans.begin(),ans.end());
    
            printf("Case %d: ",++ca);
            for(int i=0;i<ans.size();i++) printf("%c",ans[i]);
            printf("
    ");
        }
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    OpenGL开发环境简介
    EditPlus详解
    cocos2d-x游戏引擎核心之十二——3.x新特性
    创龙OMAPL138的NMI中断
    创龙OMAPL138的SPI FLASH读写
    itop4412学习-超级块操作
    创龙6748开发板加载.out出现a data verification error occurred, file load failed
    创龙OMAPL138开发板测试(1)
    DSP5509的USB协议开发
    Flask:模板
  • 原文地址:https://www.cnblogs.com/caijiaming/p/10353619.html
Copyright © 2020-2023  润新知