알고리즘/백준
BOJ 13460 구슬 탈출 2 / C++
내이름은 킹햄찌
2022. 7. 26. 17:39
https://www.acmicpc.net/problem/13460
13460번: 구슬 탈출 2
첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'
www.acmicpc.net
백준 온라인저지 13460번 구슬 탈출 2 문제입니다.
아이디어
구슬 클래스를 하나 정의해서 대부분 해당 클래스에서 처리하도록 했고, BFS를 통해 최소거리를 찾았습니다.
문제의 핵심은 파란공이 들어갔을때에 대한 처리와 두 구슬을 움직이다 곂칠때에 대한 처리라고 생각했습니다.
파린공이 들어갔을때는 해당 케이스는 통과하도록 처리했고, 곂쳐질때는 이동거리가 더 긴공이 반대로 이동하도록 처리했습니다. 자세한건 아래 주석을 통해 확인할 수 있습니다.
#include <iostream>
#include <vector>
#include <queue>
#define MAX 10
using namespace std;
int mx[4] = { 0,1,0,-1 };
int my[4] = { 1,0,-1,0 };
int ry, rx, by, bx;
bool visited[10][10][10][10];
int n, m;
vector<vector<char>> field;
//dirction
enum {
up = 0,
right = 1,
down = 2,
left = 3
};
//field element
enum {
Wall = '#',
Hole = 'O',
Red = 'R',
Blue = 'B',
None = '.'
};
//구슬
class Bead {
private:
int y;
int x;
int dirCnt;
public:
Bead() {}
Bead(int a, int b , int c) {
y = a;
x = b;
dirCnt = c;
}
//방향만 받아서 움직일수 있을때까지 움직임
int move(int dir) {
int moveCnt = 0;
while (true) {
//현재가 구멍일때
if (field[y][x] == Hole) break;
//다음이 벽일때
if (field[y + my[dir]][x + mx[dir]] == Wall) break;
y += my[dir];
x += mx[dir];
moveCnt++;
}
dirCnt++;
return moveCnt;
}
int getDircCnt() {
return dirCnt;
}
int getX() {
return x;
}
int getY() {
return y;
}
};
void setField() {
field = vector<vector<char>>(n, vector<char>(m, ' '));
}
void input() {
cin >> n >> m;
setField();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> field[i][j];
if (field[i][j] == Red) {
ry = i;
rx = j;
}
else if (field[i][j] == Blue) {
by = i;
bx = j;
}
}
}
}
void bfs() {
queue<pair<Bead, Bead>> q;
q.push({ Bead(ry,rx,0),Bead(by,bx,0) });
visited[ry][rx][by][bx] = true;
while (!q.empty()) {
Bead red = q.front().first;
Bead blue = q.front().second;
q.pop();
if (red.getDircCnt() > 9) break;
for (int i = 0; i < 4; i++) {
Bead r = red;
Bead b = blue;
int rMove = r.move(i);
int bMove = b.move(i);
//파란구슬이 먼저 들어가면 처리하지 않음
if (field[b.getY()][b.getX()] == Hole) continue;
if (field[r.getY()][r.getX()] == Hole) {
cout << r.getDircCnt();
return;
}
//두 구슬이 곂쳐질때
if (r.getY() == b.getY() && r.getX() == b.getX()) {
//이동 거리가 더 많은 구슬이 한칸 반대로 움직임
if (rMove > bMove) {
r = Bead(r.getY() - my[i], r.getX() - mx[i], r.getDircCnt());
}
else {
b = Bead(b.getY() - my[i], b.getX() - mx[i], b.getDircCnt());
}
}
if (visited[r.getY()][r.getX()][b.getY()][b.getX()]) continue;
visited[r.getY()][r.getX()][b.getY()][b.getX()] = true;
q.push({ r,b });
}
}
cout << "-1";
}
void solution() {
bfs();
}
int main(void) {
input();
solution();
}