BFS_连连看问题

来源:互联网 发布:好的莆田鞋淘宝店 编辑:程序博客网 时间:2024/06/04 20:00

连连看问题(BFS)

HNUSTOJ地址
题目描述
大家都玩过连连看吧!今天我们玩一个类似的游戏。在一个由10*10个小方格组成的矩形里有n(n<=10)对字符(它们是大写字符中的前n个)。矩形里有些位置是可以从上面走过,有些则不能。能走过的位置用’.’标识,不能的用’#’标识。如果2个相同字符是连通的(从一个字符能走到另一个字符,注意走的时候只能向上、下、左、右走。某个位置是有其他字符时,这个位置是不能走的),那么这对字符能够进行配对。如果将这对字符配对,这对字符将从这个矩形里消除,也就是说这2个字符所在的位置对于其他字符而言变成能走动了。
现在的问题是:请你决定这些字符的配对顺序(只有能配对才能进行配对),使得n对字符最后都配对成功。
输入
先给出一个正整数t(t<=10),表示有t组测试数据。
每组测试数据有10行组成,每行有10个字符。这些字符只能是’.’,’#’,或者是大写字符中的前n个。每组测试数据中不超过10对字符。
输出
如果能够使每组测试数据中的n对字符配对成功,输出配对的顺序。如果有多种配对成功的顺序,输出字典序最小的那组。
否则输出”My God!”。
样例输入
2
ABF…….
CE……..
D………
……….
……….
……….
……….
………D
……..EC
…….FBA
ABF…….
CE……..
D………
……….
……….
………#
……..#D
………#
……..EC
…….FBA
样例输出
DCABEF
My God!
思路:
此题是寻找配对问题,因此可用BFS找到配对字符,只需找到,而不用寻找最佳,对于字典序的处理,每次进行一次BFS配对成功后,再重新循环字典序(预存的处理,节省时间),队列使用的是循环队列,没用STL的原因是会导致TLE。

#include<cstdio>#include<iostream>#include<cstring>#include<queue>#include<algorithm>using namespace std;char mp[11][11];//记录地图struct Node{    int ch;//存放字符    int x;//存放位置    int y;    int flag;//判断是否已经配对,配对为1,没有配对为0};Node store[11];//字母升序存放字符int dx[4]={-1,1,0,0};int dy[4]={0,0,-1,1};int N;bool cmp(Node a,Node b){   return a.ch<b.ch;}int bfs(Node e){ Node Q[505];  int vis[10][10]={0};  vis[e.x][e.y]=2;  int base=0,tail=0;  Q[tail++]=e;  while(base!=tail)//查找队列    {   Node n=Q[base];        if(vis[n.x][n.y]!=2&&mp[n.x][n.y]=='A'+e.ch)//已经找到了匹配点,更新匹配点变成'.'        {            mp[e.x][e.y]='.';            mp[n.x][n.y]='.';            return 1;        }      else        {            for(int i=0;i<4;i++)                {                    int x=n.x+dx[i];                    int y=n.y+dy[i];                    if(x>=0&&x<10&&y>=0&&y<10&&vis[x][y]!=1&&vis[x][y]!=2&&(mp[x][y]=='.'||mp[x][y]=='A'+e.ch))                    {                        if(vis[x][y]!=2&&mp[x][y]==e.ch+'A')//如果找到匹配点,更新                            {                               mp[e.x][e.y]='.';                               mp[x][y]='.';                               return 1;                            }                        else { //该点入队咧,并且更新判重坐标                            vis[x][y]=1;                            Node nn;                            nn.ch=e.ch;                            nn.x=x;                            nn.y=y;                            Q[tail]=nn;                            tail=(tail+1)%505;                             }                    }                }        }        base=(base+1)%505;    }    return 0;//没有匹配到则返回0}int main(){   //freopen("d://in.txt","r",stdin);    scanf("%d",&N);    while(N--)    {   Node st[21];        int cnt=0;        for(int i=0;i<10;i++)        {            scanf("%s",mp[i]);            for(int j=0;j<10;j++)            {                if(mp[i][j]!='.'&&mp[i][j]!='#')//将所有的点储存起来                {                    st[cnt].x=i;                    st[cnt].y=j;                    st[cnt].ch=mp[i][j]-'A';                    st[cnt].flag=0;cnt++;                }            }        }        sort(st,st+cnt,cmp);//进行升序排序        int sum=0;        int cr[11];//存放字符        for(int i=0,j=0;i<cnt;i+=2,j++)        {            store[j]=st[i];//过滤掉重复的点            //printf("%c",store[j].ch+'A');        }        for(int i=0;i<cnt/2;i++)        {            if(store[i].flag==0&&bfs(store[i])) //如果找到则再一次判断            {                store[i].flag=1;                cr[sum++]=store[i].ch;                i=-1;            }        }        if(sum!=cnt/2) printf("My God!\n");        else        {            for(int i=0;i<sum;i++) printf("%c",'A'+cr[i]);            printf("\n");        }    }}