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;
}