반응형
https://www.acmicpc.net/problem/3197
3197번: 백조의 호수
입력의 첫째 줄에는 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1500. 다음 R개의 줄에는 각각 길이 C의 문자열이 하나씩 주어진다. '.'은 물 공간, 'X'는 빙판 공간, 'L'은 백조가 있는 공간으로 나타낸다.
www.acmicpc.net
#include <bits/stdc++.h>
using namespace std;
int r, c;
char arr[1501][1501];
int num[1501][1501];
int unf[1501 * 1501];
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
int Find(int x) {
if (unf[x] < 0) return x;
return unf[x] = Find(unf[x]);
}
void merge(int x, int y) {
x = Find(x);
y = Find(y);
if (x == y) return;
unf[x] = y;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
memset(unf, -1, sizeof(unf));
vector<pair<int, int> > swan;
queue<pair<int, int> > water;
cin >> r >> c;
for (int i = 0; i < r; i++) {
string s;
cin >> s;
for (int j = 0; j < c; j++) {
arr[i][j] = s[j];
if (arr[i][j] == 'L') {
swan.push_back({ i,j });
arr[i][j] = '.';
}
else if (arr[i][j] == 'X') {
num[i][j] = -1;
continue;
}
water.push({ i,j });
}
}
//독립적으로 물이 있는 영역을 구해준다.
int cnt = 1;
queue<pair<int, int> > Q;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (num[i][j] == 0) {
num[i][j] = cnt;
Q.push({ i,j });
while (!Q.empty()) {
int x = Q.front().first;
int y = Q.front().second;
Q.pop();
for (int k = 0; k < 4; k++) {
int nx = x + dx[k];
int ny = y + dy[k];
if (nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
if (num[nx][ny] == 0) {
num[nx][ny] = num[x][y];
Q.push({ nx,ny });
}
}
}
cnt++;
}
}
}
int t = 0;
if (Find(num[swan[0].first][swan[0].second]) == Find(num[swan[1].first][swan[1].second])) {
cout << t << '\n';
return 0;
}
while (!water.empty()) {
int q = water.size();
//물로 빙하를 물로 만든다.
for (int j = 0; j < q; j++) {
int x = water.front().first;
int y = water.front().second;
water.pop();
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
if (arr[nx][ny] == 'X') {
arr[nx][ny] = '.';
num[nx][ny] = num[x][y];
water.push({ nx,ny });
}
else {
merge(num[x][y], num[nx][ny]);
}
}
}
//현재 얼음이 물이 되어서 합쳐져야 될 영역이 있다면 합친다
q = water.size();
for (int j = 0; j < q; j++) {
int x = water.front().first;
int y = water.front().second;
water.pop();
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
if (arr[nx][ny] == '.') {
merge(num[x][y], num[nx][ny]);
}
}
water.push({ x,y });
}
t++;
if (Find(num[swan[0].first][swan[0].second]) == Find(num[swan[1].first][swan[1].second])) {
cout << t << '\n';
return 0;
}
}
return 0;
}
반응형
'Algorithm > problem' 카테고리의 다른 글
백준 9938번 : 방 청소 dis-joint set C++ (0) | 2022.03.01 |
---|---|
백준 11085번 : 군사 이동 - Union & Find (0) | 2022.03.01 |
백준 14868번 : 문명 - BFS Union&Find C++ (0) | 2022.03.01 |
백준 1178번 : 간선 추가 - 오일러 경로 , Union&Find 알고리즘 (0) | 2022.02.28 |
백준 16168번 : 퍼레이드 - 오일러 회로 C++ (0) | 2022.02.28 |