문제
바닷가에 놀러 간 구름이는 모래사장에서 모래를 쌓아서 모래섬을 만들었다. 구름이는 자신이 만든 모래섬 사이에 다리를 세우고 싶어한다. 다리를 그냥 만들 수도 있지만, 구름이는 서로 떨어진 섬과 섬을 이어줄 때 다리가 의미가 있다고 생각을 했다. 그래서 구름이는 모래사장에 물을 부어서 모래섬을 여러 개의 섬으로 나누고자 한다.
모래사장은 세로의 길이가 N, 가로의 길이가 M인 직사각형 모양의 땅이다. 모래사장을 1*1 크기로 나누었을 때, 가장 왼쪽 위부터 i번째 줄의 j번째 칸의 상태를 arr[i][j]라고 표현할 수 있다. 각 칸의 상태는 0또는 1중 하나이다.
●arr[i][j]의 값이 0이라면, 그 칸은 물에 가라앉은 칸임을 의미한다.
●arr[i][j]의 값이 1이라면, 그 칸은 모래가 쌓여있는 칸임을 의미한다.
매 분마다 모래가 쌓여있는 칸 중, 다음 조건에 해당하는 칸이 동시에 물에 가라앉게 된다.
●상하좌우로 인접한 칸 중, 물에 가라앉은 칸이 존재한다.
이때 하나의 모래섬은 다음 내용을 만족한다. 모래가 쌓여있는 칸 중, 상하좌우로 인접해있는 칸끼리는 이동할 수 있다. 단, 물에 가라앉은 칸이나 모래사장의 바깥으로는 이동할 수 없다. 그리고 어떤 칸에서 다른 칸으로 이동할 수 있는 경로가 존재한다면, 두 칸은 같은 모래섬에 속해있다.
구름이는 모래섬의 개수가 두 개 이상이 될 때, 다리를 건설하려고 한다. 구름이가 물을 부은 뒤 최소 몇 분 후에 다리를 건설 할 수 있는지 출력하시오. 단, 두 개 이상의 모래섬으로 나누어지지 않는 경우에는 -1을 출력하시오.
구름 알고리즘 먼데이 챌린지 4주차 2번 단풍나무 문제와 유사한 문제이다.
크게 4가지 Phase를 구현하여 문제를 해결하였다.
1.물과 인접해 있는 모래 섬 좌표 구하기
2.물과 인접해 있는 모래 섬 물로 바꿔주기
3.모래 섬 개수 구하기
4.모래 섬 개수에 따라 다시 1번부터 진행할지 출력 후 종료 할지 판단.
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int n, m, board[101][101];
int dir[2][4] = { {-1, 1, 0, 0}, {0, 0, -1, 1} };
vector<pair<int, int>> convert;
void check(int y, int x) {
int ny, nx;
for (int i = 0; i < 4; i++) {
ny = y + dir[0][i];
nx = x + dir[1][i];
if (ny < 0 || ny > n - 1 || nx < 0 || nx > m - 1) continue;
if (!board[ny][nx]) { //인접한 곳에 물이 있다면
convert.push_back({ y, x });
break;
}
}
}
void bfs(int y, int x, vector<vector<int>>& visited) {
int cy, cx, ny, nx;
visited[y][x] = 1;
queue<pair<int, int>> q;
q.push({ y, x });
while (!q.empty()) {
cy = q.front().first;
cx = q.front().second;
q.pop();
for (int i = 0; i < 4; i++) {
ny = cy + dir[0][i];
nx = cx + dir[1][i];
if (ny < 0 || ny > n - 1 || nx < 0 || nx > m - 1) continue;
if (visited[ny][nx]) continue;
if (!board[ny][nx]) continue;
visited[ny][nx] = 1;
q.push({ ny, nx });
}
}
}
int count_island() {
int cnt = 0;
vector<vector<int>> visited(n, vector<int>(m, 0));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (board[i][j] && !visited[i][j]) {
cnt++;
bfs(i, j, visited);
}
}
}
return cnt;
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
cin >> board[i][j];
int day = 0;
while (true) {
convert.clear();
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (board[i][j] == 1) check(i, j);
for(const auto& [y, x] : convert) board[y][x] = 0;
day++;
int cnt = count_island();
if (cnt >= 2) {
cout << day;
return 0;
}
else if (cnt == 0) {
cout << -1;
return 0;
}
}
}
'Alrogithm > 구름(GOORM)' 카테고리의 다른 글
[구름 알고리즘 먼데이 챌린지] Week6 : 1. 7게임 (0) | 2022.11.14 |
---|---|
[구름 알고리즘 먼데이 챌린지] Week5 : 3. 수 이어 붙이기 (0) | 2022.11.12 |
[구름 알고리즘 먼데이 챌린지] Week5 : 1. 개미와 진딧물 (0) | 2022.11.12 |
[구름 알고리즘 먼데이 챌린지] Week4 : 4. 주차 구역 나누기 (0) | 2022.11.12 |
[구름 알고리즘 먼데이 챌린지] Week4 : 3. 거리두기 (0) | 2022.11.11 |