问题 I: BFS_连连看游戏
时间限制: 2 Sec 内存限制: 10 MB提交: 207 解决: 27
[ 提交][ 状态][ 讨论版]
题目描述
大家都玩过连连看吧!今天我们玩一个类似的游戏。在一个由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!
提示
存粹消化老师给的例码,看懂之后,自己打了一遍,测试的时候发现好多问题,慢慢的DUBUG,发现对这程序的理解加深了很多。但同时发现自己能力还是非常弱,思路已经给出来了,自己去实现,竟然还错了很多次。还得加强训练。
下面的代码,给了注释,讲的有点乱
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct q {
int x;
int y;
};
q queu[10000];
int n;
char map[16][16];
int visti[16][16];
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}}; //方向数组
int bfs(int x,int y) {
memset(visti,0,sizeof(visti));
int f=1;//头
int r=1; //尾
queu[f].x=x;
queu[f].y=y;
visti[x][y]=1;
bool flag=true;
while(f<=r && flag) {
int x1=queu[f].x;
int y1=queu[f].y;
for(int i=0; i<4; i++) {
int newx=x1+dir[i][0];
int newy=y1+dir[i][1];
if(newx<10 && newx >=0 && newy<10 && newx >=0 && !visti[newx][newy] && (map[newx][newy]=='.' || map[newx][newy]==map[x][y])) {
visti[newx][newy]=1;
++r;
queu[r].x=newx;
queu[r].y=newy;
if(map[newx][newy]==map[x][y]) {
map[newx][newy]='.';
map[x][y]='.';
flag=false;
break;
}
}
}
f++;
}
if(!flag)
return 1;
else
return 0;
}
int main() {
scanf("%d",&n);
int i,j,k;
bool endl1,endl2;
int counts;
while(getchar()!='\n');
while(n--) {
char ans[100];
for(i=0; i<10; i++)
scanf("%s",map[i]);
counts=0;
endl2=false;
while(!endl2) {
endl2=true; //26个字母都遍历完了则,都没有发现可以消掉的字母,则结束;
for(i=0; i<25&&endl2; i++) { //26个英文字母按字典序进行搜索
endl1=true;
for(j=0; j<10&&endl1; j++)
for(k=0; k<10&& endl1; k++) { //遍历改图,如果有该字母,则进行bfs,看是否能消掉
if(map[j][k]==i+65) {
if(bfs(j,k)) //如果能消掉,则从头再来遍历
endl1=endl2=false;
else
endl1=false; //如果该字母不能消掉,则i++,遍历下一个字母;
}
}
}
if(!endl2) { //该字母能消掉,保存到ANS数组里
ans[++counts]=i-1; //之所以是i-1,是因为在for循环中最后i还执行了一次i++;
}
}
for(i=0; i<10&&endl2; i++)
for(j=0; j<10&&endl2; j++) //一发现有没有消掉的字母,立刻跳出。
if(map[i][j]!='.' && map[i][j]!='#')
endl2=false;
if(!endl2)
printf("My God!");
else
for(i=1; i<=counts; i++)
printf("%c",ans[i]+65);
printf("\n");
}
}