알고리즘/BOJ

백준 2933번 미네랄

꾸준함. 2019. 10. 7. 05:21

문제 링크입니다: https://www.acmicpc.net/problem/2933

 

2933번: 미네랄

문제 창영과 상근은 한 동굴을 놓고 소유권을 주장하고 있다. 두 사람은 막대기를 서로에게 던지는 방법을 이용해 누구의 소유인지를 결정하기로 했다. 싸움은 동굴에서 벌어진다. 동굴에는 미네랄이 저장되어 있으며, 던진 막대기가 미네랄을 파괴할 수도 있다. 동굴은 R행 C열로 나타낼 수 있으며, R×C칸으로 이루어져 있다. 각 칸은 비어있거나 미네랄을 포함하고 있으며, 네 방향 중 하나로 인접한 미네랄이 포함된 두 칸은 같은 클러스터이다. 창영은 동굴의 왼쪽에

www.acmicpc.net

 

해당 문제는 새로 생긴 클러스터가 바닥에 닿을 때까지 클러스터들을 한칸씩 내리는 것이 핵심인 문제였습니다.

새로 생긴 클러스터들을 찾기 위해 DFS 함수를 이용하였고 클러스터 구성원 중 하나의 'x'라도 바닥에 닿아있다면 flag = true를 부여하여 내리는 작업을 하지 않았습니다.

코드가 조금 길지만 주석을 참고하면 쉽게 이해할 수 있을 것이라고 생각합니다.

 

#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;
}
view raw .cpp hosted with ❤ by GitHub

개발환경: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