728x90
이 문제는 두가지 방식으로 풀 수 있다.
하나는 BFS 를 두 번 사용해서 푸는 방법과
또 다른 하나는 Disjoint-Set 과 BFS 를 섞어서 푸는 방식이 있다.
나는 BFS 를 두번쓰는 방식으로 처리하였다.
먼저 입력 받을때, 백조의 좌표를 따로 저장하고 (vector<pair<int, int>> swan), 물의 좌표를 저장한다 (queue<pair<int, int>> water_queue)
물의 좌표를 저장하는 이유는 하루씩 지날때 마다 인접한 얼음들을 녹여야하기 때문이다.
BFS 를 두개를 작성했는데, 하나는 백조가 이동하기 위한 BFS 함수 (swan_bfs()) 를 통해서 백조가 다른 백조와 만날 수 있는지 확인한다. 만났다면 프로그램 종료하고 아니면 얼음을 녹이기 위해 물 근처를 탐색하는 BFS 함수 (water_bfs()) 를 수행한다.
두함수를 수행했음에도 찾지 못했으면 다음날로 넘어가고 다시 반복한다.
여기서 next_queue 라는 또 다른 큐 변수를 만들었는데
이는 처음에는 백조의 좌표를 넣어서 탐색하지만, 다음날 부터는 백조가 있던 그자리는 방문 처리가 이미 되어 있어서 또 다시 방문할 필요가 없으며 그냥 두 백조가 만날 수 있는지 없는지만 판별하면 되기 때문에, next_queue 에는, 다음날에 녹은 얼음의 좌표를 담으면 거기서 부터 BFS 를 수행해서 다른 백조와 만날 수 있는지만 판별하면 되기 때문이다.
Disjoint-set 으로 푸는 방법은 아래 참조
- C++
#include <bits/stdc++.h>
#define MAX 1500
using namespace std;
int R, C, answer;
int dy[4] = {-1, 1, 0, 0};
int dx[4] = {0, 0, -1, 1};
string adj[MAX];
bool visited[MAX][MAX];
vector<pair<int, int>> swan; // 백조 좌표
queue<pair<int, int>> water_queue, q; // 물 좌표, BFS 탐색큐
bool flag; // 탐색 도중 두 백조가 만나는 경우
void swan_bfs() {
queue<pair<int, int>> next_queue;
while(!q.empty()) {
int y = q.front().first;
int x = q.front().second;
q.pop();
if (y == swan[1].first && x == swan[1].second) {
flag = true; // 두 백조가 만남
break;
}
for (int i = 0; i < 4; ++i) {
int ny = y + dy[i];
int nx = x + dx[i];
if (ny < 0 || ny >= R || nx < 0 || nx >= C || visited[ny][nx]) continue;
visited[ny][nx] = true;
if (adj[ny][nx] == 'X') {
next_queue.push({ny, nx});
continue;
}
q.push({ny, nx});
}
}
q = next_queue;
}
void water_bfs() {
int size = water_queue.size();
while(size--) {
int y = water_queue.front().first;
int x = water_queue.front().second;
water_queue.pop();
for (int i = 0; i < 4; ++i) {
int ny = y + dy[i];
int nx = x + dx[i];
if (ny < 0 || ny >= R || nx < 0 || nx >= C) continue;
if (adj[ny][nx] == 'X') {
adj[ny][nx] = '.';
water_queue.push({ny, nx});
}
}
}
}
int main() {
cin.tie(0); ios_base::sync_with_stdio(0);
cin >> R >> C;
for (int i = 0; i < R; ++i) {
cin >> adj[i];
for (int j = 0; j < C; ++j) {
if (adj[i][j] == 'L') swan.push_back({i, j});
if (adj[i][j] == '.' || adj[i][j] == 'L') water_queue.push({i, j});
}
}
q.push(swan[0]);
visited[swan[0].first][swan[0].second] = true;
while(1) {
swan_bfs();
if (flag) break; // 도중에 두 백조가 만난 경우
water_bfs();
answer++;
}
cout << answer;
return 0;
}
|
cs |
728x90
'PS' 카테고리의 다른 글
BOJ 16120 - PPAP (0) | 2021.02.21 |
---|---|
BOJ 2515 - 전시장 (0) | 2021.02.21 |
BOJ 1450 - 냅색문제 (0) | 2021.02.20 |
BOJ 1826 - 연료 채우기 (0) | 2021.02.20 |
BOJ 1202 - 보석 도둑 (0) | 2021.02.20 |