[BOJ]
[BOJ] [C++] 3197 백조의 호수
준제
2023. 8. 28. 20:18
https://www.acmicpc.net/problem/3197
3197번: 백조의 호수
입력의 첫째 줄에는 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1500. 다음 R개의 줄에는 각각 길이 C의 문자열이 하나씩 주어진다. '.'은 물 공간, 'X'는 빙판 공간, 'L'은 백조가 있는 공간으로 나타낸다.
www.acmicpc.net
BFS문제인데, '두 백조가 만날 때 까지 반복한다'는 조건이 달렸다. 배열의 크기가 1500*1500으로 크기 때문에, 효율적인 코드 작성이 필요하다.
다음과 같은 기본 구조를 가지고 문제를 해결한다.
기본 구조
입력을 받고, 물 공간과 백조 위치를 Queue에 넣는다
>>> BFS 1회 실행
>>> 백조가 만나는지 확인
>>> 만났다면 break, 만나지 않았다면 반복
출력한다.
위 방식대로 작성하면 정답은 맞지만 시간초과가 나온다. 따라서 시간을 줄일 수 있는 방법을 고려해야한다.
BFS에서 시간을 단축하긴 어렵기 때문에, 백조가 만나는지 확인하는 코드를 효율적으로 구상 해 보자.
IsSwanMeet
>>> 백조 위치에서 빙판과 만날 때 까지 BFS 실행
>>> 빙판과 만나면 임시Queue에 push, 물과 만나면 Queue에 push, 백조와 만나면 break
>>> 탐색이 끝나고 Queue가 비면, Queue에 임시Queue 삽입
위 방법으로 백조의 움직임 또한 BFS로 구현하면 시간 복잡도를 줄일 수 있다.
// ANSWER
#include <queue>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
using pii = pair<int,int>;
struct Swan {int r,c; };
vector <Swan> swan;
queue <pii> swanQ;
queue <pii> waterQ;
int R, C;
char arr[1501][1501];
int check[1501][1501];
int date = 0;
int di[5]={1, 0, -1, 0};
int dj[5]={0, 1, 0, -1};
void MeltIce(){
int WaterSize = waterQ.size();
while(WaterSize--){
int ii = waterQ.front().first;
int jj = waterQ.front().second;
waterQ.pop();
for(int k = 0 ; k < 4 ; k ++){
int ni = ii + di[k];
int nj = jj + dj[k];
if(0 > ni || ni >= R || 0 > nj || nj >= C) continue;
if(arr[ni][nj] != 'X') continue;
waterQ.push({ni,nj});
arr[ni][nj] = '.';
}
}
}
bool IsSwanMeet(){
queue <pii> swanQ_next;
while(!swanQ.empty()){
int ii = swanQ.front().first;
int jj = swanQ.front().second;
swanQ.pop();
if(ii == swan[1].r && jj == swan[1].c) return true;
for(int k = 0 ; k < 4 ; k ++){
int ni = ii + di[k];
int nj = jj + dj[k];
if(0 > ni || ni >= R || 0 > nj || nj >= C) continue;
if(check[ni][nj]) continue;
check[ni][nj] = 1;
if(arr[ni][nj] == 'X') swanQ_next.push({ni,nj});
else swanQ.push({ni,nj});
}
}
swanQ = swanQ_next;
return false;
}
int main(){
scanf("%d %d", &R, &C);
for (int i = 0 ; i < R ; i ++) {
char tmp[1501];
scanf("%s", tmp);
for (int j = 0 ; j < C ; j ++) {
arr[i][j] = tmp[j];
if (arr[i][j] != 'X') {
waterQ.push({i, j});
}
if (arr[i][j] == 'L') {
swan.push_back({i,j});
}
}
}
swanQ.push({swan[0].r,swan[0].c});
while(1){
if (IsSwanMeet()) break;
MeltIce();
date++;
}
printf("%d", date);
return 0;
}