백준 #13459 구슬 탈출
빨간 구슬과 파란 구슬이 있는 판을 10 회 이하로 기울여 빨간 구슬이 구멍에 빠지게 할 수 있는지 구하는 문제.
BFS를 사용하여 가능한지의 여부를 구할 수 있다.
구슬이 두 개여서 한 번 기울일 때마다 두 구슬의 좌표를 각각 구해주고 겹치지 않게 해주어야 한다.
위 문제가 이 문제의 업그레이드된 버전이지만, 위 문제를 먼저 풀어버려서 이 문제를 코드만 수정해 쉽게 풀어버렸다.
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int N, M;
char board[10][10];
int visit[10][10][10][10]; //빨간 구슬, 파란 구슬의 좌표에 따른 판 기울임 횟수
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
void emptyBuffer() { // '\n' 캐릭터 소모
while(getchar() != '\n') {}
}
bool redLater(pair<int, int> rPos, pair<int, int> bPos, int dir) { //빨간 구슬이 늦게 굴렀는지 반환
bool isRedLater = false;
if(dir == 0 && rPos.second < bPos.second) {
isRedLater = true;
}
else if(dir == 1 && rPos.second > bPos.second) {
isRedLater = true;
}
else if(dir == 2 && rPos.first < bPos.first) {
isRedLater = true;
}
else if(dir == 3 && rPos.first > bPos.first) {
isRedLater = true;
}
return isRedLater;
}
/* 입력: 빨간 구슬의 x, y 좌표, 파란 구슬의 x, y 좌표
출력: 빨간 구슬을 구멍에 넣을 수 있는 최소 판 기울임 횟수(10 초과인 경우 -1) */
int bfs(int rx, int ry, int bx, int by) {
queue<pair<pair<int, int>, pair<int, int>>> q;
q.push({{rx, ry}, {bx, by}});
visit[rx][ry][bx][by] = 0;
while(!q.empty()) {
pair<int, int> tmpR = q.front().first;
pair<int, int> tmpB = q.front().second;
q.pop();
for(int i = 0; i < 4; i++) {
int rNx = tmpR.first;
int rNy = tmpR.second;
int bNx = tmpB.first;
int bNy = tmpB.second;
int depth = visit[rNx][rNy][bNx][bNy]; //판의 기울임 횟수
if(depth > 9) {
break;
}
bool redInHole = false;
bool bluInHole = false;
while(board[rNx][rNy] != '#') { //빨간 구슬이 벽을 만날 때까지 탐색
if(board[rNx][rNy] == 'O') {
redInHole = true;
break;
}
rNx += dx[i];
rNy += dy[i];
}
if(!redInHole) { //벽을 만난 경우 좌표 - 1
rNx -= dx[i];
rNy -= dy[i];
}
while(board[bNx][bNy] != '#') { //파란 구슬이 벽을 만날 때까지 탐색
if(board[bNx][bNy] == 'O') {
bluInHole = true;
break;
}
bNx += dx[i];
bNy += dy[i];
}
if(!bluInHole) { //벽을 만난 경우 좌표 - 1
bNx -= dx[i];
bNy -= dy[i];
}
if(rNx == bNx && rNy == bNy && !redInHole) { //빨간 구슬과 파란 구슬의 좌표가 겹칠 시 나중에 온 구슬의 좌표 - 1
if(redLater(tmpR, tmpB, i)) {
rNx -= dx[i];
rNy -= dy[i];
}
else {
bNx -= dx[i];
bNy -= dy[i];
}
}
if(redInHole && !bluInHole) { //빨간 구슬은 구멍에 들어가고 파란 구슬은 구멍에 들어가지 않을 시 1 반환
return 1;
}
if(!bluInHole && visit[rNx][rNy][bNx][bNy] == -1) { //파란 구슬이 구멍에 들어가지 않고 visit한 적이 없을 시 queue에 push
q.push({{rNx, rNy}, {bNx, bNy}});
visit[rNx][rNy][bNx][bNy] = depth + 1;
}
}
}
return 0; //10번 초과 기울여도 빨간 구슬을 구멍에 넣을 수 없을 시 0 반환
}
int main() {
memset(visit, -1, sizeof(visit));
cin >> N >> M;
int rX, rY, bX, bY;
emptyBuffer();
for(int i = 0; i < N; i++) {
for(int j = 0; j < M; j++) {
board[i][j] = getchar();
if(board[i][j] == 'R') {
rX = i;
rY = j;
board[i][j] = '.';
}
else if(board[i][j] == 'B') {
bX = i;
bY = j;
board[i][j] = '.';
}
}
emptyBuffer();
}
cout << bfs(rX, rY, bX, bY);
return 0;
}
Comments