dfs 알고리즘 문제이다.
여기서 중요한 포인트가 1. 같은 색인지 2. 방문했던 점인지 이 두 가지를 살펴보면 된다.
사이클이란 이미 방문했던 같은 색의 점을 다시 방문하는 것이다.
하지만 위의 정의대로라면 방금 왔던 점으로 되돌아가는 것도 사이클이 된다고 할 수 있다. 이러면 문제의 정의대로 4개 이상의 점으로 이뤄졌다고 할 수 없기 때문에 이 부분만 주의하면 된다.
즉, 인접한 점이 같은 색이며 방문했었지만 방금 왔던 점은 아니다.
-> 사이클이다.
위의 개념을 가지고 dfs 알고리즘으로 점들을 순환하며 사이클을 찾으면 종료하면 된다.
주의점으로 출력이 "Yes", "No" 이다.
public class bj16929 {
public static boolean cycle = false;
public static int M, N;
public static Character[][] box;
public static boolean[][] visited;
static int[] xMove = {1, -1, 0, 0};
static int[] yMove = {0, 0, -1, 1};
public static void main(String[] args) throws Exception {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
String[] split2 = line.split(" ");
N = Integer.parseInt(split2[0]);
M = Integer.parseInt(split2[1]);
box = new Character[N][M];
visited = new boolean[N][M];
for (int i = 0; i < N; i++) {
String line1 = br.readLine();
char[] charArray = line1.toCharArray();
for (int j = 0; j < M; j++) {
box[i][j] = charArray[j];
}
}
for (int i = 0; i < N; i++) {
if (cycle) break;
for (int j = 0; j < M; j++) {
if (!visited[i][j]) {
if (cycle) break;
dfs(new spot(i, j), new spot(-1, -1));
}
}
}
if (cycle) {
bw.write("Yes" + "\n");
} else {
bw.write("No" + "\n");
}
bw.flush();
bw.close();
br.close();
}
private static void dfs(spot start, spot last) {
// 방문 처리
visited[start.x][start.y] = true;
// 나의 상하좌우 살피기
for (int i = 0; i < 4; i++) {
if (cycle) break;
int newX = start.x + xMove[i];
int newY = start.y + yMove[i];
// 주어진 칸 안에 있는 곳 일때
if (newX >= 0 && newX < N) {
if (newY >= 0 && newY < M) {
// 같은 색이다.
if (box[newX][newY].equals(box[start.x][start.y])) {
// 방문했었으며 방금 왔던 점이 아니다 -> 사이클
if ((visited[newX][newY]) && (last.x != newX || last.y != newY)) {
cycle = true;
}
// 방문한 적 없으니 방문한다.
else if (!visited[newX][newY]) dfs(new spot(newX, newY), start);
}
}
}
}
}
static class spot {
int x;
int y;
spot(int x, int y) {
this.x = x;
this.y = y;
}
}
}