新连连看

题目: 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;
}
posted @ 2012-04-16 20:52  天如er  阅读(390)  评论(0编辑  收藏  举报