Sample Input 1
3 4
AAAA
ABCA
AAAA
Sample Output 1
Yes
题目中给的n、m的范围是0~50,所以可以直接暴力枚举,把所有点都遍历一遍,用 flag 标记是否有环出现,一旦 flag==1,跳出所有循环,难点是如何找环,其实只需要那开始dfs的点,和遍历到最后的点做一下判断,看它们是否相邻,且ans要大于等于4,即 if(ans>=4&&( (abs(x1-ex)==0 && abs(y1-ey)==1 ) || ( abs(x1-ex)==1 && abs(y1-ey)==0 ) ) )
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
using namespace std;
const int M=60;
char str[M][M];
int vis[M][M];
int n,m,ans,flag,ex,ey,x2,y2;
int p[2][4]={{1,-1,0,0},{0,0,1,-1}};
bool check(int x,int y){////判断是否是合法的点
if(x>=0&&x<n&&y>=0&&y<m&&!vis[x][y])
return true;
return false;
}
void dfs(int x1,int y1){
ans++;//记录步数
vis[x1][y1]=1;
for(int i=0;i<4;i++){
x2=x1+p[0][i];
y2=y1+p[1][i];
if(check(x2,y2)){
if(str[x1][y1]==str[x2][y2]){////如果满足条件就继续搜索
dfs(x2,y2);
}
}
}
//判断搜到尽头的那个点是否和起点相邻,步数是否大于4
if(ans>=4&&( (abs(x1-ex)==0 && abs(y1-ey)==1 )||
( abs(x1-ex)==1 && abs(y1-ey)==0 ))){//注意括号的使用,这里wa了好几次
flag=1;
return ;
}
else ans=0;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
memset(str,0,sizeof(str));
for(int i=0;i<n;i++){
scanf("%s",str[i]);
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
ans=0;
flag=0;
memset(vis,0,sizeof(vis));//每搜一个点,判断完后都要清除标记,以便后面的点的搜索
if(!vis[i][j]){
ex=i;//开始坐标
ey=j;//开始坐标
dfs(i,j);
if(flag) break;//跳出i
}
if(flag) break;//跳出j
}
if(flag) puts("Yes");
else puts("No");
}
return 0;
}