PS

BOJ 3197 - 백조의 호수

728x90

www.acmicpc.net/problem/3197

 

3197번: 백조의 호수

입력의 첫째 줄에는 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1500. 다음 R개의 줄에는 각각 길이 C의 문자열이 하나씩 주어진다. '.'은 물 공간, 'X'는 빙판 공간, 'L'은 백조가 있는 공간으로 나타낸다.

www.acmicpc.net

 

이 문제는 두가지 방식으로 풀 수 있다.

하나는 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 으로 푸는 방법은 아래 참조

ghdic.github.io/ps/boj-3197/

 

 

- C++

#include <bits/stdc++.h>
 
#define MAX 1500
 
using namespace std;
 
int R, C, answer;
int dy[4= {-1100};
int dx[4= {00-11};
string adj[MAX];
bool visited[MAX][MAX];
vector<pair<intint>> swan; // 백조 좌표
queue<pair<intint>> water_queue, q; // 물 좌표, BFS 탐색큐 
bool flag; // 탐색 도중 두 백조가 만나는 경우 
 
void swan_bfs() {
    queue<pair<intint>> 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