티스토리 뷰


[백준 13460번 구슬탈출2 URL]

개인적으로, 시뮬레이션 문제 중에서 제일 어려웠던 문제.....

방문 여부를 파악하기 위해 4차원 배열을 만들어야 했던 것도 생각하기 참 힘들었다.


시뮬레이션 과정은 다음과 같다.

1. 구슬을 굴린다.

 - 구슬을 굴릴 때, 두 개의 구슬이 겹치든 말든 일단 굴린다.


2. 구슬을 굴리는 도중

 - 만약, 구슬을 굴리는 도중 'O'을 만났다면, 멈춘다.


3. 구슬을 다 굴린 후

 - 파란색 구슬이 'O'에 빠졌는지 "먼저" 확인한다. 파란색 구슬이 'O'에 빠졌다면 탐색을 종료한다.

 - 파란색 구슬은 'O'에 빠지지 않고, 빨간색 구슬이 'O' 빠졌다면 정답을 출력한다.

 - 어느 구슬도 'O'에 빠지지 않았다면, 두 구슬의 위치가 같은지 확인한다.

 - 두 구슬의 위치가 같다면, 초기 위치의 선행 관계에 따라 위치를 조정한다.


4. 반복한다.


[소스 코드]

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
 
    public static final int RED = 0, BLUE = 1;
    public static int N, M;
    public static char[][] map;
    public static boolean[][][][] visited;
    public static int[] dirX = new int[] { 001-1 }; // 동서남북
    public static int[] dirY = new int[] { 1-100 };
    public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 
    public static void main(String[] args) throws Exception {
 
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
 
        map = new char[N][M];
        visited = new boolean[10][10][10][10];
 
        Node node = new Node();
        node.cnt = 0;
 
        for (int i = 0; i < N; i++) {
            String str = br.readLine();
            for (int j = 0; j < M; j++) {
                map[i][j] = str.charAt(j);
                if (map[i][j] == 'R') {
                    node.rRow = i;
                    node.rCol = j;
                } else if (map[i][j] == 'B') {
                    node.bRow = i;
                    node.bCol = j;
                }
            }
        }
        bfs(node);
    }
 
    public static void bfs(Node ball) {
 
        Queue<Node> q = new LinkedList<Node>();
        q.offer(ball);
 
        while (!q.isEmpty()) {
 
            Node node = q.poll();
            visited[node.rRow][node.rCol][node.bRow][node.bCol] = true;
 
            //11번 이상 굴렸을 경우 -1을 출력한다.
            if (node.cnt >= 10) {
                System.out.println(-1);
                return;
            }
            
            //현재 두 구슬의 위치를 기준으로 동,서,남,북 으로 굴려본다.
            for (int dir = 0; dir < 4; dir++) {
 
                //파란색 구슬을 먼저 굴린다.
                int bnRow = node.bRow;
                int bnCol = node.bCol;
                while (map[bnRow + dirX[dir]][bnCol + dirY[dir]] != '#') {
                    bnRow += dirX[dir];
                    bnCol += dirY[dir];
                    if (map[bnRow][bnCol] == 'O') {
                        break;
                    }
                }
                
                //그 다음, 빨간색 구슬을 굴린다.
                int rnRow = node.rRow;
                int rnCol = node.rCol;
                while (map[rnRow + dirX[dir]][rnCol + dirY[dir]] != '#') {
                    rnRow += dirX[dir];
                    rnCol += dirY[dir];
                    if (map[rnRow][rnCol] == 'O') {
                        break;
                    }
                }
                
                //파란색 구슬이 'O'에 빠졌다면, 탐색을 멈춘다.
                if (map[bnRow][bnCol] == 'O')
                    continue;
                
                //빨간색 구슬만 'O'에 빠졌다면, 정답을 출력한다.
                if (map[rnRow][rnCol] == 'O') {
                    System.out.println(node.cnt + 1);
                    return;
                }
                
                //두 구슬의 위치가 같다면, 위치를 조정한다.
                if (rnRow == bnRow && rnCol == bnCol) {
 
                    switch (dir) {
 
                    case 0// 동
                        if (node.rCol > node.bCol)
                            bnCol -= 1;
                        else
                            rnCol -= 1;
                        break;
                    case 1// 서
                        if (node.rCol > node.bCol)
                            rnCol += 1;
                        else
                            bnCol += 1;
                        break;
                    case 2// 남
                        if (node.rRow > node.bRow)
                            bnRow -= 1;
                        else
                            rnRow -= 1;
                        break;
                    case 3// 북
                        if (node.rRow > node.bRow)
                            rnRow += 1;
                        else
                            bnRow += 1;
                        break;
                    }
                }
                //두 구슬을 굴린 후의 각각의 위치가 처음 탐색하는 것이라면 큐에 넣는다.
                if (!visited[rnRow][rnCol][bnRow][bnCol]) {
                    q.offer(new Node(rnRow, rnCol, bnRow, bnCol, node.cnt + 1));
                }
            }
        }
        System.out.println(-1);
 
    }
 
    public static void showMap(int[][] map) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }
}
 
class Node {
 
    int rRow;
    int rCol;
    int bRow;
    int bCol;
    int cnt;
 
    public Node(int rRow, int rCol, int bRow, int bCol, int cnt) {
        this.rRow = rRow;
        this.rCol = rCol;
        this.bRow = bRow;
        this.bCol = bCol;
        this.cnt = cnt;
    }
 
    public Node() {
    }
 
}
 
cs


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
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 31
글 보관함