문제 원본 : https://www.acmicpc.net/problem/3197
3197번: 백조의 호수
입력의 첫째 줄에는 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1500. 다음 R개의 줄에는 각각 길이 C의 문자열이 하나씩 주어진다. '.'은 물 공간, 'X'는 빙판 공간, 'L'은 백조가 있는 공간으로 나타낸다.
www.acmicpc.net


#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int R, C;
char lake[1500][1500];
bool checked[1500][1500];
queue<pair<int, int>> q;
pair<int, int> swan;
queue<pair<int, int>> swanQ;
bool swanChecked[1500][1500];
int dir[4][2] = { {-1,0},{0,1},{1,0},{0,-1} };
int main() {
cin.tie(NULL);
ios_base::sync_with_stdio(false);
cin >> R >> C;
for (int i = 0; i < R; ++i) {
for (int j = 0; j < C; ++j) {
cin >> lake[i][j];
if (lake[i][j] == 'L') {
swan = make_pair(i, j);
}
if (checked[i][j] == false && j > 0 && lake[i][j] == 'X' && (lake[i][j - 1] == '.' || lake[i][j - 1] == 'L')) {
q.push(make_pair(i, j));
checked[i][j] = true;
}
if (j > 0 && checked[i][j - 1] == false && (lake[i][j] == '.' || lake[i][j] == 'L') && lake[i][j - 1] == 'X') {
q.push(make_pair(i, j - 1));
checked[i][j - 1] = true;
}
if (checked[i][j] == false && i > 0 && lake[i][j] == 'X' && (lake[i - 1][j] == '.' || lake[i - 1][j] == 'L')) {
q.push(make_pair(i, j));
checked[i][j] = true;
}
if (i > 0 && checked[i - 1][j] == false && (lake[i][j] == '.' || lake[i][j] == 'L') && lake[i - 1][j] == 'X') {
q.push(make_pair(i - 1, j));
checked[i - 1][j] = true;
}
}
}
swanQ.push(swan);
swanChecked[swan.first][swan.second] = true;
int cnt = 0;
while (true) {
queue<pair<int, int>> buf;
queue<pair<int, int>> swanBuf;
while (!swanQ.empty()) {
int r = swanQ.front().first;
int c = swanQ.front().second;
swanQ.pop();
for (int i = 0; i < 4; ++i) {
int nr = r + dir[i][0];
int nc = c + dir[i][1];
if (nr < 0 || nr >= R || nc < 0 || nc >= C) {
continue;
}
if (swanChecked[nr][nc] == false && lake[nr][nc] == 'L') {
cout << cnt << "\n";
return 0;
}
if (swanChecked[nr][nc] == false && lake[nr][nc] == '.') {
swanQ.push(make_pair(nr, nc));
swanChecked[nr][nc] = true;
}
if (swanChecked[nr][nc] == false && lake[nr][nc] == 'X') {
swanBuf.push(make_pair(nr, nc));
swanChecked[nr][nc] = true;
}
}
}
while (!q.empty()) {
int r = q.front().first;
int c = q.front().second;
q.pop();
lake[r][c] = '.';
for (int i = 0; i < 4; ++i) {
int nr = r + dir[i][0];
int nc = c + dir[i][1];
if (nr < 0 || nr >= R || nc < 0 || nc >= C) {
continue;
}
if (checked[nr][nc] == false && lake[nr][nc] == 'X') {
buf.push(make_pair(nr, nc));
checked[nr][nc] = true;
}
}
}
++cnt;
q = buf;
swanQ = swanBuf;
}
}
- 전체를 BFS 돌리면 시간초과가 나기 때문에 처음에 녹을 좌표만 큐에 넣고 만날 때까지 BFS 반복
- 반복 BFS 돌릴 때도 다음에 녹을 좌표만 큐에 삽입
'알고리즘 > BOJ' 카테고리의 다른 글
| [BOJ] 17136. 색종이 붙이기 (0) | 2022.02.15 |
|---|---|
| [BOJ] 16137. 견우와 직녀 (0) | 2022.02.10 |
| [BOJ] 2749. 피보나치 수 3 (0) | 2022.02.09 |
| [BOJ] 2042. 구간 합 구하기 (0) | 2022.02.08 |
| [BOJ] 17837. 새로운 게임 2 (0) | 2022.02.07 |