[백준 3197번] 백조의 호수

2021. 12. 2. 22:26·알고리즘 문제풀이/백준
반응형

문제 링크: https://www.acmicpc.net/problem/3197

 

3197번: 백조의 호수

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

www.acmicpc.net

<문제 풀이> BFS

하루가 지날 때마다 모든 물을 확인해서 얼음을 녹이고 백조의 처음 시작 위치에서 BFS를 돌리면

얼음을 녹이는데 O(RC), 백조 BFS O(RC)

->O(R^2 * C^2)이 되기 때문에 시간 초과가 나게 됩니다.

 

그래서 시간을 단축하는 방법은

1. 하루가 지날 때 마다 빙판을 녹일 물을 탐색하는데 이미 확인했던 물은 무시

2. 물 주위에 빙판은 다음에 물이 되니깐 빙판을 물로 바꾸고 다음에 물의 탐색을 그 빙판이 있던 'X' 위치에서 시작합니다.

-> 다음 물의 시작 위치를 저장하고 있어야 되기 때문에 임시 큐가 필요합니다. (tempWater)

 

그리고 하루가 지날 때마다 백조 한 마리를 BFS로 움직여보면 되는데

1. 하루가 지날 때 마다 백조를 움직일 때 이미 방문했던 물은 무시

->이미 방문했던 물을 무시해도 되는 이유는 백조의 경로가 중요하지 않기 때문입니다.

->빙판 때문에 막혀서 못만났으니깐 백조를 처음 위치에서 다시 시작할 필요 없이 빙판을 만난 직전의 위치에서 시작하면 됩니다. 

2. 백조가 다른 백조를 만나면 종료

3. 백조의 다음 위치가 빙판 'X'이면 다음 날에 현재 위치부터 다시 백조 BFS 진행

->다음 백조의 시작 위치를 저장하고 있어야 되기 때문에 임시 큐가 필요합니다.(tempSwan)

<C++ 소스 코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
using namespace std;
 
#define X first 
#define Y second 
 
char board[1500][1500];
bool visited[1500][1500];
int dx[4] = {0, -1, 0, 1};
int dy[4] = {1, 0, -1, 0};
int r, c;
int res = 0;
void bfs() {
    queue<pair<int, int> > swan;
    queue<pair<int, int>> tempSwan;
    queue<pair<int, int> > water;
    queue<pair<int, int> > tempWater;
    bool found = false;
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            if (board[i][j] == '.') {
                water.push({ i, j });
            }
            else if (!found && board[i][j] == 'L') {
                swan.push({ i, j });
                visited[i][j] = true;
                found = true;
                water.push({ i, j });
            }
            else if (found && board[i][j] == 'L') {
                water.push({ i, j });
            }
        }
    }
    while (true) {
        while (!tempSwan.empty()) { //백조의 다음 시작 위치를 백조 큐에 넣음
            swan.push(tempSwan.front());
            visited[tempSwan.front().X][tempSwan.front().Y] = true;
            tempSwan.pop();
        }
        while (!swan.empty()) { //백조 이동 BFS
            auto cur = swan.front(); swan.pop();
            for (int dir = 0; dir < 4; dir++) {
                int nx = cur.X + dx[dir];
                int ny = cur.Y + dy[dir];
                if (nx < 0 || ny < 0 || nx >= r || ny >= c) continue;
                if (visited[nx][ny]) continue;
                if (board[nx][ny] == '.') {
                    visited[nx][ny] = true;
                    swan.push({ nx, ny });
                }
                else if (board[nx][ny] == 'X') {
                    tempSwan.push({ cur.X, cur.Y });
                }
                else if (board[nx][ny] == 'L') {
                    return;
                }
            }
        }
        res++;
        while (!water.empty()) { //얼음 녹이기 BFS
            auto cur = water.front(); water.pop();
            for (int dir = 0; dir < 4; dir++) {
                int nx = cur.X + dx[dir];
                int ny = cur.Y + dy[dir];
                if (nx < 0 || ny < 0 || nx >= r || ny >= c) continue;
                if (visited[nx][ny]) continue;
                if (board[nx][ny] == 'X') {
                    board[nx][ny] = '.';
                    tempWater.push({ nx, ny });
                }
            }
        }
        while (!tempWater.empty()) { //물의 다음 시작 위치는 얼음이 녹은 위치
            water.push(tempWater.front());
            tempWater.pop();
        }
    }
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> r >> c;
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            cin >> board[i][j];
        }
    }
    bfs();
    cout << res;
    return 0;
}
 
Colored by Color Scripter
cs
반응형
저작자표시 (새창열림)

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 16920번] 확장 게임  (0) 2021.12.08
[백준 11967번] 불켜기  (0) 2021.12.04
[백준 4963번] 섬의 개수  (0) 2021.11.25
[백준 1600번] 말이 되고픈 원숭이  (0) 2021.11.25
[백준 17071번] 숨바꼭질 5  (0) 2021.11.25
'알고리즘 문제풀이/백준' 카테고리의 다른 글
  • [백준 16920번] 확장 게임
  • [백준 11967번] 불켜기
  • [백준 4963번] 섬의 개수
  • [백준 1600번] 말이 되고픈 원숭이
슥지니
슥지니
개발 블로그
  • 슥지니
    슥지니의 코딩노트
    슥지니
  • 전체
    오늘
    어제
    • 분류 전체보기 (198)
      • 알고리즘 문제풀이 (158)
        • 백준 (158)
      • 알고리즘 (6)
      • Node.js (2)
        • MongoDB (1)
        • 기타 (1)
      • spring (0)
      • 가상화폐 (1)
        • 바이낸스(Binance) (1)
      • C++ 테트리스 게임 (0)
      • C++ (10)
      • 안드로이드 프로그래밍 (21)
        • 코틀린 (21)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Kotlin
    C++
    구현
    C
    백트랙킹
    백준
    그래프
    알고리즘
    dfs
    그리디
    우선순위 큐
    BFS
    코틀린을 활용한 안드로이드 프로그래밍
    자료구조
    시뮬레이션
    콘솔 테트리스 게임
    코틀린
    dp
    다이나믹 프로그래밍
    콘솔
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
슥지니
[백준 3197번] 백조의 호수
상단으로

티스토리툴바