문제 링크입니다: https://www.acmicpc.net/problem/2933
2933번: 미네랄
문제 창영과 상근은 한 동굴을 놓고 소유권을 주장하고 있다. 두 사람은 막대기를 서로에게 던지는 방법을 이용해 누구의 소유인지를 결정하기로 했다. 싸움은 동굴에서 벌어진다. 동굴에는 미네랄이 저장되어 있으며, 던진 막대기가 미네랄을 파괴할 수도 있다. 동굴은 R행 C열로 나타낼 수 있으며, R×C칸으로 이루어져 있다. 각 칸은 비어있거나 미네랄을 포함하고 있으며, 네 방향 중 하나로 인접한 미네랄이 포함된 두 칸은 같은 클러스터이다. 창영은 동굴의 왼쪽에
www.acmicpc.net
해당 문제는 새로 생긴 클러스터가 바닥에 닿을 때까지 클러스터들을 한칸씩 내리는 것이 핵심인 문제였습니다.
새로 생긴 클러스터들을 찾기 위해 DFS 함수를 이용하였고 클러스터 구성원 중 하나의 'x'라도 바닥에 닿아있다면 flag = true를 부여하여 내리는 작업을 하지 않았습니다.
코드가 조금 길지만 주석을 참고하면 쉽게 이해할 수 있을 것이라고 생각합니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <string> | |
#include <cstring> | |
using namespace std; | |
const int MAX = 100; | |
typedef struct | |
{ | |
int y, x; | |
}Dir; | |
Dir moveDir[4] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} }; | |
int R, C; | |
int N; | |
bool flag; | |
bool visited[MAX][MAX]; | |
vector<pair<int, int>> cluster; | |
string graph[MAX]; | |
void DFS(int y, int x) | |
{ | |
if (y == R - 1) | |
{ | |
flag = true; | |
return; | |
} | |
for (int k = 0; k < 4; k++) | |
{ | |
int nextY = y + moveDir[k].y; | |
int nextX = x + moveDir[k].x; | |
if (nextY < 0 || nextY >= R || nextX < 0 || nextX >= C || visited[nextY][nextX]) | |
{ | |
continue; | |
} | |
if (graph[nextY][nextX] == '.') | |
{ | |
continue; | |
} | |
visited[nextY][nextX] = true; | |
cluster.push_back({ nextY, nextX }); | |
DFS(nextY, nextX); | |
} | |
} | |
int main(void) | |
{ | |
ios_base::sync_with_stdio(0); | |
cin.tie(0); | |
cin >> R >> C; | |
for (int i = 0; i < R; i++) | |
{ | |
cin >> graph[i]; | |
} | |
cin >> N; | |
vector<int> stick(N); | |
for (int i = 0; i < N; i++) | |
{ | |
cin >> stick[i]; | |
} | |
for (int i = 0; i < stick.size(); i++) | |
{ | |
int y = R - stick[i]; | |
int x = -1; | |
if (i % 2 == 0) | |
{ | |
for (int j = 0; j < C; j++) | |
{ | |
if (graph[y][j] == 'x') | |
{ | |
x = j; | |
break; | |
} | |
} | |
} | |
else | |
{ | |
for (int j = C - 1; j >= 0; j--) | |
{ | |
if (graph[y][j] == 'x') | |
{ | |
x = j; | |
break; | |
} | |
} | |
} | |
// 부실 미네랄이 없다면 | |
if (x == -1) | |
{ | |
continue; | |
} | |
graph[y][x] = '.'; | |
for (int k = 0; k < 4; k++) | |
{ | |
int nextY = y + moveDir[k].y; | |
int nextX = x + moveDir[k].x; | |
if (nextY < 0 || nextY >= R || nextX < 0 || nextX >= C) | |
{ | |
continue; | |
} | |
if (graph[nextY][nextX] == '.') | |
{ | |
continue; | |
} | |
memset(visited, false, sizeof(visited)); | |
cluster.clear(); | |
flag = false; | |
cluster.push_back({ nextY, nextX }); | |
visited[nextY][nextX] = true; | |
DFS(nextY, nextX); | |
// 클러스터 구성원 중 하나라도 바닥에 닿아있다면 | |
if (flag) | |
{ | |
continue; | |
} | |
// 바닥에 닿을 때까지 한 칸씩 아래로 | |
while (1) | |
{ | |
bool down = true; | |
for (int j = 0; j < cluster.size(); j++) | |
{ | |
graph[cluster[j].first][cluster[j].second] = '.'; | |
} | |
for (int j = 0; j < cluster.size(); j++) | |
{ | |
int y = cluster[j].first + 1; | |
int x = cluster[j].second; | |
if (y == R || graph[y][x] == 'x') | |
{ | |
down = false; | |
break; | |
} | |
} | |
for (int j = 0; j < cluster.size(); j++) | |
{ | |
if (down) | |
{ | |
cluster[j].first++; | |
} | |
graph[cluster[j].first][cluster[j].second] = 'x'; | |
} | |
if (!down) | |
{ | |
break; | |
} | |
} | |
} | |
} | |
for (int i = 0; i < R; i++) | |
{ | |
cout << graph[i] << "\n"; | |
} | |
return 0; | |
} |


개발환경:Visual Studio 2017
지적, 조언, 질문 환영입니다! 댓글 남겨주세요~
반응형
'알고리즘 > BOJ' 카테고리의 다른 글
백준 1981번 배열에서 이동 (2) | 2019.10.08 |
---|---|
백준 2957번 이진 탐색 트리 (0) | 2019.10.08 |
백준 2186번 문자판 (7) | 2019.10.03 |
백준 5635번 생일 (2) | 2019.10.02 |
백준 6118번 숨바꼭질 (0) | 2019.09.29 |