[백준] 2615번 오목
문제 접근
사용 알고리즘
완전 탐색 + DFS
방향 설정
오목인지 판단을 하기 위해선 한 점에 대해서 총 8방향
을 봐야한다.
하지만 2중 for문을 사용할 때, 위에서 아래
/ 왼쪽에서 오른쪽
으로 탐색을 하게 된다면,
파란색을 칠해진 방향
에 대해선 볼 필요가 없다 (중복되기 때문)
5목 판단
DFS 시작
2중 for문을 이용하여 위에서 아래
/ 왼쪽에서 오른쪽
으로 탐색을 하다가 0
이 아닌 값일 경우, 이 점으로부터 DFS
를 시작하면 된다.
DFS의 인자
bool dfs(int y, int x, int color, int dir, int depth);
시작 주소, color값, 방향, 깊이 (연속적으로 놓인 바둑알 수)
방문처리
위의 사진처럼 완전탐색
으로 바둑알의 시작점
을 찾기 때문에 해당 방향으로 탐색을 했었어도 중복해서 세는 경우가 생긴다. 이 경우를 없애주기 위해서 해당 방향으로 진행한 적
이 있는지 방문처리를 해줘야 한다.
필자는 방문처리를 위해 DFS
를 진행할 때마다 visited[y][x][dir] = true
로 선언해주면서 방문처리를 진행하였다.
DFS 종료 (+ 오목 판단)
- 오목판을 넘어감 (경계)
DFS
를 처음 들어왔을 당시의color
값과 현재의color
값이 다름- 해당 방향으로 탐색한 적이 있는 경우
위의 조건에 걸렸을 때, depth (연속적으로 놓인 바둑알의 수)
가 5인지 판단하면 된다.
좌표 출력
zero indexing
방식으로 진행했기 때문에 5목이 되었을 경우, y
값과 x
값에 각각 1씩 더해주어 반환을 해주었다.
주의
왼쪽 아래로 오목이 형성된 경우, 출력은 맨 왼쪽 아래의
위치를 출력해 줘야 한다. 따라서 이 경우에 한해서만 y
값에는 5를 더해주고, x
값에는 3을 빼주어 반환하였다.
소스코드
#include <iostream>
#define MAX 19
using namespace std;
int board[MAX][MAX];
bool v[MAX][MAX][4] = { 0, };
int dy[] = { 0, 1, 1, 1 };
int dx[] = { 1, 0, 1, -1 };
bool dfs(int y, int x, int color, int dir, int depth) {
if (v[y][x][dir]) { // y, x에서 dir 방향으로 이동한 적이 있다 = 이 경로는 오목이 되지 못한다.
return false;
}
// 오목 판의 경계를 넘어갔거나, 처음과 끝의 색이 다른 경우(비어있는 경우도 포함)
if (board[y][x] != color || y < 0 || x < 0 || x >= MAX || y >= MAX) {
// depth == 5 라면 true 반환, 아니라면 false 반환
return depth == 5 ? true : false;
}
// 방문처리
v[y][x][dir] = true;
int ny = y + dy[dir];
int nx = x + dx[dir];
return dfs(ny, nx, color, dir, depth + 1);
}
pair<pair<int, int>, int> solve() {
for (int y = 0; y < MAX; y++) {
for (int x = 0; x < MAX; x++) {
// dir[] = { 오른쪽, 아래쪽, 오른쪽 아래, 왼쪽 아래 }
for (int dir = 0; dir < 4; dir++) {
if (board[y][x] != 0) { // 오목 판에 흰색 또는 검은색 돌이 올려져 있다면
if (dfs(y, x, board[y][x], dir, 0)) { // 5목이 되는 지 판단.
// zero-indexing 으로 풀었으므로, 리턴값은 y, x 에 각각 1 씩 더해줘야 함.
if (dir != 3) {
return { { y + 1, x + 1 }, board[y][x] };
}
// 왼쪽 아래로 오목이 형성된 경우, 시작지점은 왼쪽 아래의 위치임.
else {
return { { y + 5, x - 3 }, board[y][x] };
}
}
}
}
}
}
return { { 0, 0 }, 0 };
}
int main() {
for (int y = 0; y < MAX; y++) {
for (int x = 0; x < MAX; x++) {
cin >> board[y][x];
}
}
pair<pair<int, int>, int> result = solve();
if (result.second == 0) {
cout << "0";
}
else {
cout << result.second << "\n";
cout << result.first.first << " " << result.first.second;
}
return 0;
}
Author And Source
이 문제에 관하여([백준] 2615번 오목), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@alirz-pixel/백준-2615번-오목저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)