반응형
문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - Two Dots (16929)
[ 문제 ]
Two Dots는 Playdots, Inc.에서 만든 게임이다. 게임의 기초 단계는 크기가 N×M인 게임판 위에서 진행된다.
각각의 칸은 색이 칠해진 공이 하나씩 있다. 이 게임의 핵심은 같은 색으로 이루어진 사이클을 찾는 것이다.
다음은 위의 게임판에서 만들 수 있는 사이클의 예시이다.
점 k개 d1, d2, ..., dk로 이루어진 사이클의 정의는 아래와 같다.
- 모든 k개의 점은 서로 다르다.
- k는 4보다 크거나 같다.
- 모든 점의 색은 같다.
- 모든 1 ≤ i ≤ k-1에 대해서, di와 di+1은 인접하다. 또, dk와 d1도 인접해야 한다. 두 점이 인접하다는 것은 각각의 점이 들어있는 칸이 변을 공유한다는 의미이다.
게임판의 상태가 주어졌을 때, 사이클이 존재하는지 아닌지 구해보자.
[ 입력 ]
첫째 줄에 게임판의 크기 N, M이 주어진다. 둘째 줄부터 N개의 줄에 게임판의 상태가 주어진다. 게임판은 모두 점으로 가득차 있고, 게임판의 상태는 점의 색을 의미한다. 점의 색은 알파벳 대문자 한 글자이다.
[ 출력 ]
사이클이 존재하는 경우에는 "Yes", 없는 경우에는 "No"를 출력한다.
[ 제한 ]
- 2 ≤ N, M ≤ 50
[ 코드 ]
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
/* 이 문제를 dfs로 풀어야 하는 이유
1. 같은 색깔 내에서도 시작점이 어디냐에 따라 사이클 가능 여부가 달라진다.
- bfs로 풀면 시작점을 다르게 해서 일일이 검사를 해야한다
- dfs로 풀면 어디서 시작하든 이동횟수는 일정하게 증가하므로, 그 차이만 계산하면 된다.
* 인접한 노드를 먼저 방문하는 것(BFS)보다, 하나의 노드를 계속 방문하는 방식(DFS)가 더 적합.
2. 최소거리를 계산하는게 아니라, 가능 여부만 구하는 것이다,
*/
char a[51][51]; // 게임판의 상태 입력 (색깔 입력)
int d[51][51];
bool check[51][51]; // 거쳐온 부분인지 check
int n, m; // 게임판의 크기 n,m (n : 세로, m : 가로)
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };
bool bfs(int x, int y, int cnt, char color) {
if (check[x][y]) // 이미 거쳐온 경우 (check가 true인 경우)
{
// 사이클 형성 조건
if (cnt - d[x][y] >= 4) // 현재까지 진행해온 횟수 - check를 변환했을 때의 횟수 >= 4
{
return true; // true 반환
}
else
{
return false;
}
}
// 거쳐오지 않은 경우 (check가 false인 경우)
check[x][y] = true;
d[x][y] = cnt; // 방문하게 되는 시작점의 d배열에, 현재 cnt를 저장한다.
for (int k = 0; k < 4; k++)
{
int nx = x + dx[k];
int ny = y + dy[k];
if (0 <= nx && nx < n && 0 <= ny && ny < m)
{
if (a[nx][ny] == color)
{
if (bfs(nx, ny, cnt + 1, color)) // 이전에 true로 반환되었다면
{
return true; // 마지막까지 이 함수가 실행된다면, return true로 마무리
}
}
}
}
return false; // 함수가 실행이 안되었다면, return false로 마무리
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n; i++)
{
for (int k = 0; k < m; k++)
{
if (check[i][k]) // dfs로 진행했기 때문에, 이미 같은 색깔은 다 확인한 것
{
continue;
}
memset(d, 0, sizeof(d));
bool ok = bfs(i, k, 1, a[i][k]);
if (ok)
{
cout << "Yes" << '\n';
return 0;
}
}
}
cout << "No" << '\n';
return 0;
}
반응형
'문과 코린이의, [C. C++] 기록 > C++ 백준 문제풀이' 카테고리의 다른 글
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 서울 지하철 2호선 (16947) (0) | 2021.11.11 |
---|---|
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 나이트의 이동 (7562) (0) | 2021.10.01 |
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 토마토 (7576) (0) | 2021.10.01 |
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 미로 탐색 (2178) (0) | 2021.09.27 |
[문과 코린이의 IT 기록장] C++ 백준 문제풀이[그래프 1] - 섬의 개수 (4963) (0) | 2021.09.27 |