1
+ import java .io .*;
2
+ import java .util .*;
3
+
4
+ //bfs + 비트마스킹
5
+ //처음에 dfs 로 접근했는데, 그럼 모든 경로를 다 탐색 해 버리더라구요 최단거리 문제는 bfs 로 풀기!
6
+ public class YJ_1194 {
7
+ static class Pos {
8
+ int x ;
9
+ int y ;
10
+ int distance ;
11
+ int hasKey ;
12
+
13
+ public Pos (int x , int y , int distance , int hasKey ) {
14
+ this .x = x ;
15
+ this .y = y ;
16
+ this .distance = distance ;
17
+ this .hasKey = hasKey ;
18
+ }
19
+ }
20
+
21
+ static final char EXIT = '1' ;
22
+ static final char CURRENT = '0' ;
23
+ static final char WALL = '#' ;
24
+
25
+ static int N ;
26
+ static int M ;
27
+ static char [][] maze ;
28
+
29
+ public static void main (String [] args ) throws IOException {
30
+ BufferedReader br = new BufferedReader (new InputStreamReader (System .in ));
31
+ StringTokenizer st = new StringTokenizer (br .readLine ());
32
+ N = Integer .parseInt (st .nextToken ());
33
+ M = Integer .parseInt (st .nextToken ());
34
+ maze = new char [N ][M ];
35
+ visited = new boolean [N ][M ][64 ]; //★키 6개 2^6 = 64
36
+
37
+ int x = 0 ;
38
+ int y = 0 ;
39
+ for (int i =0 ; i <N ; i ++) {
40
+ String data = br .readLine ();
41
+ for (int j =0 ; j <M ; j ++) {
42
+ maze [i ][j ] = data .charAt (j );
43
+ if (maze [i ][j ] == CURRENT ) {
44
+ x = i ;
45
+ y = j ;
46
+ }
47
+ }
48
+ }
49
+
50
+ System .out .println (escape (x ,y ));
51
+ }
52
+
53
+ static boolean [][][] visited ;
54
+ static int escape (int x , int y ){
55
+ Deque <Pos > pq = new ArrayDeque <>();
56
+ int [] dx = {0 ,1 ,0 ,-1 };
57
+ int [] dy = {1 ,0 ,-1 ,0 };
58
+
59
+ pq .offer (new Pos (x ,y ,0 ,0 ));
60
+ visited [x ][y ][0 ] = true ;
61
+
62
+ while (!pq .isEmpty ()) {
63
+ Pos pos = pq .poll ();
64
+ if (maze [pos .x ][pos .y ] == EXIT ) {
65
+ return pos .distance ;
66
+ }
67
+
68
+ for (int d =0 ; d <4 ; d ++){
69
+ int nx = pos .x + dx [d ];
70
+ int ny = pos .y + dy [d ];
71
+ if (stop (nx ,ny , pos .hasKey )){
72
+ continue ;
73
+ }
74
+
75
+ int key = pos .hasKey ;
76
+ if (maze [nx ][ny ] >= 'A' && maze [nx ][ny ] <= 'F' ) {
77
+ if ((key & 1 <<(maze [nx ][ny ] - 'A' )) > 0 ){ //가지고 있는 키와 일치하는 경우 (A=65)
78
+ visited [nx ][ny ][key ] = true ;
79
+ }else {
80
+ continue ;
81
+ }
82
+ }else if (maze [nx ][ny ] >= 'a' && maze [nx ][ny ] <= 'f' ){ //키를 주운 경우
83
+ key |= 1 <<(maze [nx ][ny ] - 'a' ); //a=97
84
+ visited [nx ][ny ][key ] = true ;
85
+ }else {
86
+ visited [nx ][ny ][key ] = true ; //'.'
87
+ }
88
+
89
+ pq .offer (new Pos (nx ,ny ,pos .distance +1 ,key ));
90
+ }
91
+ }
92
+
93
+ return -1 ;
94
+ }
95
+
96
+ static private boolean stop (int x , int y , int hasKey ){
97
+ return x < 0 || x >= N || y < 0 || y >= M || maze [x ][y ] == WALL || visited [x ][y ][hasKey ];
98
+ }
99
+
100
+ }
0 commit comments