zoukankan      html  css  js  c++  java
  • 新连连看

    题目: http://acm.hrbeu.edu.cn/index.php?act=problem&id=1005&cid=18

    Description
    
    大家都玩过连连看吧!今天我们玩一个类似的游戏。在一个由10*10个小方格组成的矩形里有n(n<=10)对字符(它们是大写字符中的前n个)。矩形里有些位置是可以从上面走过,有些则不能。能走过的位置用'.'标识,不能的用'#'标识。如果2个相同字符是连通的(从一个字符能走到另一个字符,注意走的时候只能向上、下、左、右走。某个位置是有其他字符时,这个位置是不能走的),那么这对字符能够进行配对。如果将这对字符配对,这对字符将从这个矩形里消除,也就是说这2个字符所在的位置对于其他字符而言变成能走动了。
    
    现在的问题是:请你决定这些字符的配对顺序(只有能配对才能进行配对),使得n对字符最后都配对成功。
    
    Input
    
    先给出一个正整数t(t<=10),表示有t组测试数据。
    每组测试数据有10行组成,每行有10个字符。这些字符只能是'.''#',或者是大写字符中的前n个。每组测试数据中不超过10对字符。
    
    Output
    
    如果能够使每组测试数据中的n对字符配对成功,输出配对的顺序。如果有多种配对成功的顺序,输出字典序最小的那组。
    否则输出"My God!"。
    
    Sample Input
    
    2
    ABF.......
    CE........
    D.........
    ..........
    ..........
    ..........
    ..........
    .........D
    ........EC
    .......FBA
    ABF.......
    CE........
    D.........
    ..........
    ..........
    .........#
    ........#D
    .........#
    ........EC
    .......FBA
    
    Sample Output
    
    DCABEF
    My God!

    解题思路:

    用map存储每对字符的位置, map有自动排序的功能, 所以默认是以字典顺序遍历的. 在遍历map中的每个字符时, 检测当前字符是否可以连通至另一相同字符, 检查连通性可以用广度优先算法(深度优先重复太多).

    #include <iostream>
    #include <map>
    #include <string>
    #include <queue>
    #include <iterator>
    using namespace std;
    
    const int N = 10;
    int n;
    char bon[N][N];
    
    struct point{
        int x;
        int y;
    } point1, point2;
    
    
    map<char, point> m;
    map<char, point>::iterator it;
    char c;
    
    bool visit[N][N];
    int step[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    int basei ;
    int basej ;
    
    
    /************************************************************************/
    /*    广度优先算法         需要使用队列                                 */
    /************************************************************************/
    bool bfs(point p, char base){
    
        queue<point> points;                                                //存储可走节点的队列
        points.push(p);
        memset(visit,false,sizeof(visit));                                    //重要: 算法开始前将所有位置设置为未访问false;
        while(!points.empty()){                                                //队列不空时循环
            point tmp = points.front();
            points.pop();
            int i = tmp.x;
            int j = tmp.y;
            for(int k=0;k<4;k++)                                            //遍历周围4个方向的节点
            {
                int ti=i+step[k][0];
                int tj=j+step[k][1];
                if(ti>=0 &&ti<N && tj>=0&&tj<N &&bon[ti][tj]==base && !visit[ti][tj]) {    
                    if (basei !=ti || basej!=tj)   //不能等于他自己
                    {
                        bon[ti][tj] = '.';
                        return true;
                    }
                    else {
                        visit[ti][tj] = true;
                    }
                }
                if(ti>=0 &&ti<N && tj>=0&&tj<N &&bon[ti][tj]=='.' && !visit[ti][tj])    //如果是可行节点'.' ,将其加入队列中.
                {    
                    visit[ti][tj] = true;
                    point2.x = ti;
                    point2.y = tj;
                    points.push(point2);                                                //将可走节点压入队列中
                }
            }
        }
    
    
        return false;
    }
    
    int main(){
        cin>>n;
        for (int i=0; i<n; i++)
        {
            for (int j=0; j<N; j++)
            {
                for (int k=0; k<N; k++)
                {
                    point1.x = j;
                    point1.y = k;
                    cin>>c;
                    if (c != '.' && c != '#')
                    {
                        m[c] = point1;
                    }
                    bon[j][k] = c;
                }
            }
    
            string ans = "";
            if (m.empty())                                    //没有任何字符的情况
            {
                cout<<"My God!"<<endl;
                return 1;
            }
            
            while(!m.empty()){                                //map中还有字符就循环
                int flag = 0;
                for (it = m.begin(); it != m.end(); ++it) {
                    point tmp = it->second;
                    char tmpc = it->first;
                    basei = tmp.x;
                    basej = tmp.y;
                    if(bfs(tmp, tmpc)){                        //当前字符能够消除
                        flag = 1;
                        ans = ans + tmpc;
                        bon[tmp.x][tmp.y] = '.';
                        m.erase(tmpc);
                        break;
                    }
                }
    
                if (flag == 0)                                //所有字符都不能消除.
                {
                    ans = "My God!";
                    break;
                }
            }
            cout<<ans<<endl;
            m.clear();                                        //重要: 将上一组数据清除.
        }
        return 0;
    }
  • 相关阅读:
    题目1009:二叉搜索树
    腾讯云API 生成Authentication Header加密字符串 C#代码示例
    《神经网络与深度学习》
    《神经网络与深度学习》第一章 使用神经网络来识别手写数字(三)- 用Python代码实现
    Rust语言的多线程编程
    C# DataTable的Select()方法不支持 != 判断
    《神经网络与深度学习》第一章 使用神经网络来识别手写数字(二)- 用梯度下降来训练学习
    C# 对多个文件进行zip压缩
    《神经网络与深度学习》:第一章 使用神经网络来识别手写数字(一)
    谷歌浏览器如何查看或获取Cookie字符串
  • 原文地址:https://www.cnblogs.com/myfjd/p/2452641.html
Copyright © 2011-2022 走看看