알고리즘 풀이/백준
자바(Java) 백준 13460 구슬 탈출 2 풀이
Ssshane
2022. 7. 26. 00:54
반응형
문제
https://www.acmicpc.net/problem/13460
13460번: 구슬 탈출 2
첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'
www.acmicpc.net
풀이
이 문제는 Bfs를 사용하여 풀었습니다. 생각해줄 조건이 조금 까다롭습니다. 두 구슬을 동시에 움직이므로 생각해줘야 할게 많아진 것 같습니다.
- 먼저 빨간 구슬과 파란 구슬의 초기 위치를 저장합니다.
- 큐에 정보를 넣기 위해 빨간 구슬의 위치, 파란 구슬의 위치, 움직인 횟수 정보를 가지고 있는
PairBeads
클래스를 만듭니다. - bfs는 다음과 같은 과정으로 진행됩니다.
- 움직인 횟수가 10번 이상이라면 다음 PairBeads 객체를 꺼냅니다.
- 상하좌우 4가지 방향으로 두 구슬을 이동시킵니다.
- 움직이는 도중에 구멍으로 빠지는지 체크해줍니다.
- 빨간 구슬만 구멍에 빠졌다면 카운트 값을 리턴합니다.
- 파란 구슬이 빠졌다면 해당 경우의 수는 제외하고 다음 큐를 진행합니다.
- 경우의 수를 줄이기 위해 한 방향으로 구슬 이동을 시도 할때 두 구슬이 움직이지 않았다면 큐에 넣지 않습니다.
- 구슬이 겹쳐진 경우에는 원래 위치에서 뒤에 있던 구슬을 바뀐 위치에서 뒷쪽으로 이동하도록 해줍니다.
자세한 내용은 코드 주석을 참고해주세요.
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static int n;
static int m;
static char[][] board;
static int[] dx = {1, -1, 0, 0};
static int[] dy = {0, 0, 1, -1};
// 빨간 구슬과 파란 구슬의 위치와 bfs에 필요한 카운트 값을 가지고 있는 클래스
static class PairBeads {
int redX;
int redY;
int blueX;
int blueY;
int cnt;
public PairBeads(int redX, int redY, int blueX, int blueY, int cnt) {
this.redX = redX;
this.redY = redY;
this.blueX = blueX;
this.blueY = blueY;
this.cnt = cnt;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
board = new char[n][m];
for (int i = 0; i < n; i++) {
board[i] = br.readLine().toCharArray();
}
PairBeads pb = new PairBeads(0, 0, 0, 0, 0);
// 빨간 구슬과 파란 구슬의 초기 위치를 찾습니다.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (board[i][j] == 'R') {
pb.redX = i;
pb.redY = j;
board[i][j] = '.';
}
if (board[i][j] == 'B') {
pb.blueX = i;
pb.blueY = j;
board[i][j] = '.';
}
}
}
System.out.println(bfs(pb));
}
static int bfs(PairBeads pb) {
Queue<PairBeads> queue = new LinkedList<>();
queue.offer(pb);
while (!queue.isEmpty()) {
PairBeads beads = queue.poll();
// 10번 움직인 경우에는 패스합니다.
if (beads.cnt == 10) {
continue;
}
for (int d = 0; d < 4; d++) {
int redX = beads.redX;
int redY = beads.redY;
int blueX = beads.blueX;
int blueY = beads.blueY;
boolean isRedHole = false;
boolean isBlueHole = false;
// 빨간 구슬을 해당 방향으로 벽과 마주할 때 까지 이동시킵니다.
while (true) {
int newRedX = redX + dx[d];
int newRedY = redY + dy[d];
if (board[newRedX][newRedY] == '#') {
break;
}
// 빨간 구슬이 구멍에 빠진 경우 체크합니다.
if (board[newRedX][newRedY] == 'O') {
isRedHole = true;
break;
}
redX = newRedX;
redY = newRedY;
}
// 파란 구슬을 해당 방향으로 벽과 마주할 때 까지 이동시킵니다.
while (true) {
int newBlueX = blueX + dx[d];
int newBlueY = blueY + dy[d];
if (board[newBlueX][newBlueY] == '#') {
break;
}
// 파란 구슬이 구멍에 빠진 경우 체크합니다.
if (board[newBlueX][newBlueY] == 'O') {
isBlueHole = true;
break;
}
blueX = newBlueX;
blueY = newBlueY;
}
// 만약 파란 구슬이 구멍에 빠졌다면 실패입니다.
if (isBlueHole) {
continue;
} else if (isRedHole) {
// 빨간 구슬만 구멍에 빠졌다면 시도한 카운트 값을 반환합니다.
return beads.cnt + 1;
}
// 경우의 수를 줄이기 위해 두 구슬의 위치가 그대로인 경우에는 큐에 집어넣지 않습니다.
if (beads.redX == redX && beads.redY == redY && beads.blueX == blueX && beads.blueY == blueY) {
continue;
}
// 구슬이 같은 선상에 위치해 겹쳐지는 경우에는 구슬이 겹치지 않도록 이동해줍니다.
if (redX == blueX && redY == blueY) {
// 구슬이 아랫쪽으로 움직인 경우
if (d == 0) {
if (beads.redX < beads.blueX) {
redX--;
} else {
blueX--;
}
} else if (d == 1) {
// 구슬이 윗쪽으로 움직인 경우
if (beads.redX < beads.blueX) {
blueX++;
} else {
redX++;
}
} else if (d == 2) {
// 구슬이 오른쪽으로 움직인 경우
if (beads.redY < beads.blueY) {
redY--;
} else {
blueY--;
}
} else if (d == 3) {
// 구슬이 왼쪽으로 움직인 경우
if (beads.redY < beads.blueY) {
blueY++;
} else {
redY++;
}
}
}
queue.offer(new PairBeads(redX, redY, blueX, blueY, beads.cnt + 1));
}
}
return -1;
}
}
반응형