개인사
[G4] 백준 16929번 Two Dots C++ 깊이 우선 탐색 본문
728x90

리뷰

https://www.acmicpc.net/problem/16929
4방향으로 탐색이 가능한 맵 상에서 동일한 알파벳으로 이루어진 사이클이 존재하는지 판단하는 문제
전역 변수
- N : 배열의 최대 크기를 정의할 상수 변수
- s : 맵 정보를 저장할 문자열 배열
- n, m : 맵의 세로/가로 크기를 저장할 변수
- v : 각 칸에 방문한 시간을 저장할 2차원 배열
- cycle : 사이클이 발생했는지 여부를 저장할 변수
- dx, dy : 4방향 탐색을 위한 방향 배열
함수
1. dfs
void dfs(int cx, int cy, const char& ch, int t) {
if (cycle) return;
for (int i = 0; i < 4; ++i) {
int nx = cx + dx[i], ny = cy + dy[i];
if (0 <= nx && nx < n && 0 <= ny && ny < m && s[nx][ny] == ch) {
if (!v[nx][ny]) {
v[nx][ny] = t + 1;
dfs(nx, ny, ch, t + 1);
}
if (v[nx][ny]) {
if (abs(v[nx][ny] - t) < 2) continue;
else {
cycle = true;
return;
}
}
}
}
}
맵을 탐색하며 동일한 색을 이어가며 사이클이 발생하는지 여부를 체크하기 위한 함수
문제풀이
- n, m값을 입력 받고, 맵 정보를 입력 받아 s배열을 초기화한다.
- 맵의 각 칸을 순회하며 이미 방문한 칸이라면 continue처리한다.
- 방문하지 않은 칸이라면 값을 1로 저장하고, dfs함수에 좌표와 문자, 시작 시간을 매개변수로 전달하여 호출한다.
- dfs함수 내부에서 변수 cx, cy에 좌표를, ch에 문자를, t에 방문 시간을 매개변수로 받아 파싱한다.
- 기저 조건으로 cycle이 true라면 이미 사이클을 발견한 상태이므로 리턴 처리한다.
- 4방향을 탐색하며 맵의 범위 내에 있고, 동일 문자라면 일단 이동이 가능한 칸이다.
- 아직 방문하지 않은 칸이라면 v배열에 t+1을 저장하고 재귀를 이어서 수행한다.
- 이미 방문한 칸이면서 현재 칸과 시간 차이가 1이하라면 이동을 하지 않는다.
- 이미 방문한 칸이면서 현재 칸과 시간 차이가 2이상이라면 cycle을 true로 저장하고 리턴 처리한다.
트러블 슈팅
없음
참고 사항
- 방문한 시간이 2이상 차이가 나는 칸에 접근하는 경우 사이클이 발생한 경우로 보면 된다.
정답 코드
#include<iostream>
using namespace std;
const int N = 50;
string s[N];
int n, m;
int v[N][N];
bool cycle;
int dx[] = { 1, -1, 0, 0 };
int dy[] = { 0, 0, 1, -1 };
void dfs(int cx, int cy, const char& ch, int t) {
if (cycle) return;
for (int i = 0; i < 4; ++i) {
int nx = cx + dx[i], ny = cy + dy[i];
if (0 <= nx && nx < n && 0 <= ny && ny < m && s[nx][ny] == ch) {
if (!v[nx][ny]) {
v[nx][ny] = t + 1;
dfs(nx, ny, ch, t + 1);
}
if (v[nx][ny]) {
if (abs(v[nx][ny] - t) < 2) continue;
else {
cycle = true;
return;
}
}
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for (int i = 0; i < n; ++i) cin >> s[i];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (v[i][j]) continue;
v[i][j] = 1;
dfs(i, j, s[i][j], 1);
if (cycle) break;
}
}
cout << (cycle ? "Yes" : "No");
}
728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
| [G4] 백준 22945번 팀 빌딩 C++ 투 포인터 (0) | 2025.11.21 |
|---|---|
| [G5] 백준 9024번 두 수의 합 C++ 투 포인터, 정렬 (0) | 2025.11.21 |
| [G4] 백준 1956번 운동 C++ 최단 경로, 플로이드 와샬 (0) | 2025.11.21 |
| [G5] 백준 12852번 1로 만들기 2 C++ 너비 우선 탐색 (0) | 2025.11.21 |
| [G5] 백준 12931번 두 배 더하기 C++ 그리디 알고리즘 (0) | 2025.11.21 |
