백준 3055 탈출
문제
숲이 격자로 주어진다. 고슴도치 S는 비버굴 D로 가야 하는데, 물 *이 매 분 인접한 빈 칸으로 퍼진다. 고슴도치도 매 분 인접한 빈 칸으로 이동하며, 물이 찰 칸으로는 갈 수 없다. 돌 X는 물도 고슴도치도 못 지난다. 비버굴에 도착하는 최소 시간을 구하면 된다.
- 입력: 1번째 줄에
R C, 이어서R줄의 격자(.빈칸,*물,X돌,D비버굴,S고슴도치). - 출력: 비버굴에 도착하는 최소 시간. 못 가면
KAKTUS. - 제한:
1 ≤ R, C ≤ 50.
접근
물과 고슴도치가 같은 시계로 매 분 한 칸씩 퍼진다. 그래서 두 개의 BFS를 같은 분 단위로 함께 돌린다.
매 분 순서가 중요하다.
- 물을 먼저 한 겹 확장한다. 인접한 빈 칸으로 번지되, 비버굴
D에는 물이 차지 않는다. - 그다음 고슴도치를 한 겹 확장한다. 물이 된 칸·돌은 못 간다.
물을 먼저 처리하는 게 핵심이다. 이렇게 하면 “다음 순간 물이 될 칸으로는 들어갈 수 없다”는 규칙이 자연스럽게 지켜진다 — 고슴도치가 움직이려는 시점엔 이미 그 칸이 물로 바뀌어 있으니까.
고슴도치가 비버굴에 닿는 순간의 분을 출력하고, 큐가 빌 때까지 못 닿으면 KAKTUS.
풀이
전체 코드: thxwelchs/algorithm
#include<iostream>
#include<queue>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
using namespace std;
// 백준 3055 탈출
// https://www.acmicpc.net/problem/3055
const int MAX = 51;
int R, C;
char forest[MAX][MAX];
bool visit[MAX][MAX] = { false, };
queue<pair<int, int>> water;
queue<pair<int, int>> start;
int end_x, end_y;
int dx[4] = { 0, 0, -1, 1 };
int dy[4] = { -1, 1, 0 ,0 };
int BFS() {
int cnt = 0;
while (!start.empty()) {
cnt++;
int water_size = water.size();
for (;water_size--;) {
int x = water.front().first;
int y = water.front().second;
water.pop();
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= R || ny < 0 || ny >= C) continue;
if (forest[nx][ny] == 'X' || forest[nx][ny] == 'D' || forest[nx][ny] == '*') continue;
water.push(make_pair(nx, ny));
forest[nx][ny] = '*';
}
}
int start_size = start.size();
for (;start_size--;) {
int x = start.front().first;
int y = start.front().second;
start.pop();
visit[x][y] = true;
if (x == end_x && y == end_y) {
cout << cnt - 1 << endl;
return 0;
}
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= R || ny < 0 || ny >= C) continue;
if (forest[nx][ny] == 'X' || forest[nx][ny] == '*' || visit[nx][ny]) continue;
visit[nx][ny] = true;
start.push(make_pair(nx, ny));
}
}
}
cout << "KAKTUS" << endl;
return 0;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> R >> C;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
cin >> forest[i][j];
if (forest[i][j] == 'S') start.push(make_pair(i, j));
else if (forest[i][j] == 'D') { end_x = i; end_y = j; }
else if (forest[i][j] == '*') water.push(make_pair(i, j));
}
}
BFS();
return 0;
}
댓글
GitHub(giscus) 댓글은 설정 완료 후 활성화됩니다.