티스토리 뷰
13460번: 구슬 탈출 2
첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'
www.acmicpc.net
이 문제는 예전에 풀려다가 실패하고 까먹었었던 문제인데 이번에 다시 풀어보았다. bfs 탐색을 하며 빨간 구슬 R이 구멍이 O에 들어갈 수 있는지 확인하는 문제이다.
* 놓칠 수 있는 조건들
1. 10번 이상 움직여야 하는 경우 구슬을 탈출시킬 수 없다고 판단. -1을 return 해야 함
2. 구슬의 위치를 바꿨다면 이전 구슬의 위치는 삭제 후 탐색해야 함
3. 구슬 두 개의 위치로 방문 체크를 해야 함. R은 같은 위치 B만 바뀔 경우 탐색 대상이기 때문
4. 두 구슬은 같은 위치에 있을 수 없음
=> #.R.B..# 에서 →(오른쪽) 방향으로 움직인다면 #...RB# 이렇게 됨
5. B구슬이 O에 빠진다고 바로 -1을 return 하면 안 됨. 4방향을 다 체크해야 함
6. R이 먼저 빠진다고 답을 return 하면 안 됨. 해당 이동방향에서 B도 구멍에 빠질 경우 정답이 아니기 때문
=> B 먼저 탐색하는 이유
문제풀이
- 초기 R, B위치를 저장하고 map에 기록되어있는 R, B는 빈칸인.으로 바꾼다.
- 4방향에서 한 칸만 이동 x => #까지 가거나 R과 B가 붙어있을 때까지 쭉 탐색
-> visited [R.x][R.y][B.x][B.y]로 탐색 여부 확인하면서 탐색
-
B가 구멍에 빠진다면 해당 방향은 탐색할 필요가 없으므로 oFlag를 통해 표시해주고 break
- B의 이동방향에 R이 있다면 R의 한칸뒤에 B가 위치하게 됨. flag를 통해 표시해주고 R탐색
-> 이경우 만약 R이 구멍에 빠지게 된다면 B 역시 같이 빠지므로 답이 아님
public class Ex_13460 {
static int n, m;
static char[][] map;
static boolean[][][][] visited;
static int[] dx = { 0, 1, 0, -1 };
static int[] dy = { 1, 0, -1, 0 };
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
// 삼성 sw역량 테스트-구슬탈출 2
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
map = new char[n][m];
visited = new boolean[n][m][n][m];
Pair red = null;
Pair blue = null;
for (int i = 0; i < n; i++) {
String s = br.readLine();
for (int j = 0; j < m; j++) {
map[i][j] = s.charAt(j);
if (map[i][j] == 'R') {
red = new Pair(i, j, 0);
map[i][j] = '.';
} else if (map[i][j] == 'B') {
blue = new Pair(i, j, 0);
map[i][j] = '.';
}
}
}
System.out.println(bfs(red, blue));
}
static int bfs(Pair red, Pair blue) {
Queue<Pair> redQ = new LinkedList<>();
Queue<Pair> blueQ = new LinkedList<>();
redQ.add(red);
blueQ.add(blue);
while (!redQ.isEmpty() && !blueQ.isEmpty()) {
Pair curR = redQ.poll();
Pair curB = blueQ.poll();
if (curR.time+1 > 10) //10번까지만 이동가능
return -1;
for (int i = 0; i < 4; i++) {
int rx = curR.x;
int ry = curR.y;
int bx = curB.x;
int by = curB.y;
boolean flag = false;// 이동방향에 빨간색 구슬이 있을경우
boolean oFlag = false;// 파란구슬이 구멍에 빠질경우
visited[rx][ry][bx][by] = true;
while (true) {
bx += dx[i];
by += dy[i];
if (bx == rx && by == ry) { //이동방향에 R이 있다면
flag = true;
break;
}
if (map[bx][by] == '#') { //B인덱스를 갱신
bx -= dx[i];
by -= dy[i];
break;
}
if (map[bx][by] == 'O') { //B가 구멍에 빠졌을 경우
oFlag = true;
break;
}
}
//B가 구멍에 빠진다면 탐색할필요가 없음
while (!oFlag) {
rx += dx[i];
ry += dy[i];
if (rx == bx && ry == by) {//이동방향에 B가 있다면
//B는 위의 while문에서 이미 #을 만나서 정지한상태
//B의 뒤의 인덱스에 R이 위치, 큐에 저장
if (!visited[rx - dx[i]][ry - dy[i]][bx][by]) {
redQ.add(new Pair(rx - dx[i], ry - dy[i], curR.time + 1));
blueQ.add(new Pair(bx, by, curB.time + 1));
}
break;
}
if (map[rx][ry] == '#') {
if (!visited[rx - dx[i]][ry - dy[i]][bx][by]) {
redQ.add(new Pair(rx - dx[i], ry - dy[i], curR.time + 1));
//위의 while문에서 B가 R을 만나 탐색을 종료하였으므로
//R의 뒤의 인덱스에 B가 위치, 큐에 저장
if (flag)
blueQ.add(new Pair(rx - dx[i] - dx[i], ry - dy[i] - dy[i], curR.time + 1));
//R을 만나 종료된 상태가 아니라면 원래의 B의 인덱스로 저장
else
blueQ.add(new Pair(bx, by, curB.time + 1));
}
break;
}
if (map[rx][ry] == 'O') {
//구멍을 만났지만 B가 붙어있는 경우 flag==true
if (oFlag || flag) {
break;
}
return curR.time + 1;
}
}
}
}
return -1;
}
static class Pair {
int x;
int y;
int time;
Pair(int x, int y, int time) {
this.x = x;
this.y = y;
this.time = time;
}
}
}
* 지금 다시 보니 정리할만한 코드가 있을 거 같다...
'CS공부 > 알고리즘&문제풀이' 카테고리의 다른 글
[백준 1647] 도시 분할 계획(java)-MST 프림(Prim) (0) | 2021.06.23 |
---|---|
[백준 10775] 공항 (java) (0) | 2021.06.16 |
[백준 3190]뱀/삼성 sw역량 테스트 기출(java) (0) | 2021.06.08 |
[백준 14503]로봇 청소기/삼성 sw역량 테스트 기출(java) (0) | 2021.06.03 |
[백준 2250] 트리의 높이와 너비(java)- 이진트리,중위순회 (0) | 2021.05.31 |
- Total
- Today
- Yesterday
- BFS
- 채팅
- OS
- git
- java
- 코딩테스트
- 프로그래머스
- Baekjoon
- websocket
- 백준
- 삼성 sw역량테스트
- dfs
- 자바
- Stomp
- Oracle
- 최소 스패닝 트리
- SWEA
- 알고리즘
- JavaScript
- 정렬
- 삼성 sw역량 테스트
- sockjs
- MST
- programers
- 운영체제
- Heap
- 분리 집합
- Spring
- DP
- 완전탐색
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |