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.
The 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.
Output "Yes" if there exists a cycle, and "No" otherwise.
3 4 AAAA ABCA AAAA
Yes
3 4 AAAA ABCA AADA
No
4 4 YYYR BYBY BBBY BBBY
Yes
7 6 AAAAAB ABBBAB ABAAAB ABABBB ABAAAB ABBBAB AAAAAB
Yes
2 13 ABCDEFGHIJKLM NOPQRSTUVWXYZ
No
In 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,无奈终测的时候被刷了。
其实提交的时候就感觉思路不太对,可因为pretest过了,索性就没再去细想。估计是因为很少被终测刷的缘故吧,下次要注意了…
回到这道题:
题目大意:
给你以矩阵形式存在的一些点,每个点有一种颜色,题目就是要你找出是否存在可以围成一个圈的相同颜色的点。
大致思路:
看到这道题一般人都很容易想到得用搜索做,而且是深搜,广搜应该也能做,不过会麻烦很多。
之前我想到的是每走一步,就在那一步周围(除了上一步的点)检查有没有已经走过的相同颜色的点,如果有证明可以围成一个圈。这个并不难理解。主要是检查这一过程比较麻烦,后来才想到可以利用记录每一步的深度step,只要周围的点(最大只有4个)和自己有step相差超过1的,就可以证明成立了。这样就可以同时解决是否走过(通过step[i][j]是否为0)以及方便检查的时候跳过上一步走的点。
刚开始我一直陷入一个死胡同,就是按照正常流程来讲,为了防止深搜走回头路,必须设置一个变量来记录每个点是否走过,然后要证明围成一个圈就要重新走到相同颜色的点,可是这个点很明显是肯定走过一次的,这样就出现矛盾了,苦苦思考无果。其实实际上你并不一定要走到那个点去。只要证明那个点已经走过且相同颜色且不是自己的上一步走过的点就行了。这样代码就出来了。
//cf_290_B.cpp -- Fox And Two Dots
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iomanip>
typedef long long ll;
using namespace std;
const int maxn = 50 + 10;
const int maxm = 1000 + 10;
int dx[10] = {0, 1, 0, -1};
int dy[10] = {1, 0, -1, 0};
int n, m;
char c[maxn][maxn];
int f[maxm];
int d[maxn][maxn];
int cnt = 0;
int gx, gy;
bool dfs_colour(int x, int y, int step)
{
if( cnt==0 )
{
gx = x;
gy = y;
}
cnt = 1;
d[x][y] = step;
for( int i=0; i<4; i++ )
{
int nx = x + dx[i];
int ny = y + dy[i];
if( 0<=nx && nx<n && 0<=ny && ny<m &&c[nx][ny]==c[gx][gy])
{
if( d[nx][ny] && d[nx][ny]-d[x][y]>1 )
return true;
else if( d[nx][ny]==0 )
{
if( dfs_colour(nx, ny, step+1 ) )
return true;
}
}
}
return false;
}
int main(void)
{
cin>>n>>m;
getchar();
for( int i=0; i<n; i++ )
{
for( int j=0; j<m; j++ )
{
scanf("%c", &c[i][j]);
f[c[i][j]]++;
}
getchar();
}
for( int i=0; i<n; i++ )
{
for( int j=0; j<m; j++ )
{
if( f[c[i][j]]>=4 )
{
cnt = 0;
if( d[i][j]==0 )
{
if( dfs_colour(i, j, 1) )
{
printf("Yes\n");
return 0;
}
}
}
}
}
printf("No\n");
return 0;
}