Fox Ciel is playing a mobile puzzle game called "Two Dots". The basic levels are played on a board of size n × m cells, like this:
Each cell contains a dot that has some color. We will use different uppercase Latin characters to express different colors.
The key of this game is to find a cycle that contain dots of same color. Consider 4 blue dots on the picture forming a circle as an example. Formally, we call a sequence of dots d1, d2, ..., dk a cycle if and only if it meets the following condition:
These k dots are different: if i ≠ j then di is different from dj. k is at least 4. All dots belong to the same color. For all 1 ≤ i ≤ k - 1: di and di + 1 are adjacent. Also, dk and d1 should also be adjacent. Cells x and y are called adjacent if they share an edge.Determine if there exists a cycle on the field.
InputThe first line contains two integers n and m (2 ≤ n, m ≤ 50): the number of rows and columns of the board.
Then n lines follow, each line contains a string consisting of m characters, expressing colors of dots in each line. Each character is an uppercase Latin letter.
OutputOutput "Yes" if there exists a cycle, and "No" otherwise.
Examples input 3 4 AAAA ABCA AAAA output Yes input 3 4 AAAA ABCA AADA output No input 4 4 YYYR BYBY BBBY BBBY output Yes input 7 6 AAAAAB ABBBAB ABAAAB ABABBB ABAAAB ABBBAB AAAAAB output Yes input 2 13 ABCDEFGHIJKLM NOPQRSTUVWXYZ output No NoteIn first sample test all 'A' form a cycle.
In second sample there is no such cycle.
The third sample is displayed on the picture above ('Y' = Yellow, 'B' = Blue, 'R' = Red)
题目大意:给你一张字母图,让你判断其中存在某种字母成环。
解题思路:DFS,既然让成环,那么最终又得回到起点,但是这种是不行的AA(从第一个A搜到第二个A,而第二个A又搜到了第一个A,显然不符合题意)。那么这里我们多加两个参数,来记载当前节点的父节点(即它从哪来的),当你扫下一个方向时,扫到父节点,那么就跳过,扫下一个方向,如果你找到了你曾经走过的点,那么一定成环了。总结下,就是不走回头路的找到了同胞,那么就成环了。
代码如下:
#include <cstdio> #include <cstring> char map[55][55]; int visit[55][55]; int dirn[4]={1,-1,0,0}; int dirm[4]={0,0,1,-1}; int n,m; int flag;//标记是否成环 int fx,fy; void dfs(int hang,int lie,int fn,int fm,char word)//fn、fm代表当前点的父节点 { if(flag==1)//找到环了,那么之前的每层递归都快速结束 节约时间 return ; for(int i=0;i<4;i++) { int nx=hang+dirn[i]; int ny=lie+dirm[i]; if(nx>=0&&ny>=0&&nx<n&&ny<m&&map[nx][ny]==word)//不用判断之前是否走过,因为排除了父节点再碰到之前走过的点的话,那么一定成环了 { if(nx==fn&&ny==fm)//跳过父节点 { continue; } if(visit[nx][ny]==1)//成环 { flag=1; return ; } visit[nx][ny]=1;//标记下 dfs(nx,ny,hang,lie,word);//让当前点做下一个点的父节点 } } } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%s",map[i]); } memset(visit,0,sizeof(visit)); flag=0;//初始化标记 for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { fx=-5;//初始化当前点的父节点 ,-5肯定扫不到 fy=-5; if(visit[i][j]==0)//之前标记的就不扫了 { visit[i][j]=1; dfs(i,j,fx,fy,map[i][j]); if(flag==1) { break; } } } if(flag==1) { break; } } if(flag==1) { printf("Yes\n"); } else { printf("No\n"); } return 0; }