본문으로 바로가기

[백준 9328] 열쇠 -JAVA //le_effort//

category 알고리즘 2020. 3. 4. 16:32

여러가지 아이디어가 필요한 문제였다

 

핵심 아이디어는 열쇠와 벽을 처리 해주는 것 인데

대문자로 이루어진 문은 소문자로 이루어진 열쇠가 있어야 지나 갈 수 있다

하지만 이런 경우 에는 어떻게 할 까?

 

......

.A..a

*$***

 

이 경우 일반적인 bfs 탐색을 0,0 부터 진행 할 시

A가 a보다 먼저 탐색이 진행된다

하지만 a 열쇠가 접근 할 수 있는 곳에 있으니 저 A문을 열 수 있어야 한다.

 

이는 열쇠가 없어서 못여는 문이 있을경우 일단 리스트에 넣어놓는 것 이다.

 

나는 열쇠와 문을 아스키 코드로 처리를 했는데

알파벳은 대소문자를 떠나서 A~Z 총 25개가 있다.

int tmp = 'A'-'A'  =0;

int tmp = 'B'-'A" =1;

int tmp = 'C'-'A' =2;

즉  비교대상 -'A' 가 0~25 사이면 대문자 비교대상 -'a' 가 0~25 사이면 소문자다

 

그리고 예를들어 문 A가 있다 했을때

맵에 A 가 여러개 있을 수 있으므로 리스트에 좌표를 담아줬다 이는 코드 주석설명에 있으니 참고하길 바란다.

 

맵을 왜 [h+2][w+2] 크기로 했는지 궁금한 사람은 

https://suhyeokeee.tistory.com/13?category=837216

 

[백준 9376] 탈옥 -JAVA // le_effort//

여지껏 푼 bfs 문제중에 제일 어려웠던것 같다... 맨 처음 틀린 접근 방법: 문의 개수를 카운트 하고 dfs에서 문의 개수에 도달하면 하는 방법으로 했었는데 맵이 100,100 으로 커지면 정말 말도 안되는 연산시간..

suhyeokeee.tistory.com

여길 참고하면 될 것 같다.

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
import java.io.*;
import java.util.*;
public class Main {
    static int t,h,w;
    static boolean visited[][];
    static Character map [][];
    static ArrayList<Node>[]gate;
    static boolean key[];
    static int cnt =0;
    static int dx[] = {0,0,1,-1};
    static int dy[] = {1,-1,0,0};
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        t = Integer.parseInt(br.readLine());
        
        while(t-- >0) {
            String[] input = br.readLine().split(" ");
            h = Integer.parseInt(input[0]);
            w = Integer.parseInt(input[1]);
            
            cnt=0;
            map = new Character[h+2][w+2];
            visited = new boolean[h+2][w+2];
            key = new boolean[26];
            
            gate = new ArrayList[26];
            //gate 크기가 26인 이유 A~Z가 25개니 이렇게 두고
            // A열쇠를 가지고 있는 좌표가 여러개 있을 수 있으니 gate[0] = (1,2) //( 2,3) 0 은 A를 뜻한다   
            for(int i=0; i<26; i++) {
                gate[i] = new ArrayList<>();
            }
            for(int i=0; i<h+2; i++) {
                for(int j=0; j<w+2; j++) {
                    map[i][j]='.';
                }
            }
            
            for(int i=1; i<=h; i++) {
                String str = br.readLine();
                for(int j=1; j<=w; j++) {
                    map[i][j] = str.charAt(j-1);
                }
            }
            String key_input = br.readLine();
            if(!key_input.equals("0")) {
                for(int i=0; i<key_input.length(); i++) {
                    int tmp = key_input.charAt(i) -'a';
                    key[tmp] = true;
                }
            }
            bfs();
            System.out.println(cnt);
            
        }
    }
    public static void bfs() {
        Queue<Node> q = new LinkedList<>();
        q.add(new Node(0,0));
        visited[0][0= true;
        
        while(!q.isEmpty()) {
            Node a = q.poll();
            for(int i=0; i<4; i++) {
                int nx = a.x+dx[i];
                int ny = a.y+dy[i];
                if(nx>=0 && ny>=0 && nx<h+2 && ny<w+2) {
                    if(!visited[nx][ny] && map[nx][ny]!='*') {
                        if(map[nx][ny]-'A'>=0 && map[nx][ny]-'A'<=25) {    // 알파벳 대문자를 아스키코드로 구해줌
                            if(key[map[nx][ny]-'A']) {    // 아스키코드로 열쇠를 가지고 있는지 체크
                                map[nx][ny]='.';    // 문을 열어줌
                                q.add(new Node(nx,ny));
                                visited[nx][ny]=true;
                            }
                            else {
                                // 해당하는 열쇠가 없을경우 뒤에서 열쇠가 발견 될 수 있으니 일단 gate에 넣어줌 
                                gate[map[nx][ny]-'A'].add(new Node(nx,ny));
                            }
                        }
                        else if(map[nx][ny]-'a'>=0 && map[nx][ny]-'a'<=25) {    // 아스키코드로 열쇠를 넣어줌
                            key[map[nx][ny]-'a'= true;
                            visited[nx][ny] = true;
                            q.add(new Node(nx,ny));
                        }
                        else if(map[nx][ny] == '.') {    //빈칸 인 경우 진행
                            visited[nx][ny] = true;    
                            q.add(new Node(nx,ny));
                        }
                        else if(map[nx][ny]=='$') {    //문서 발견시 cnt ++
                            cnt++;
                            visited[nx][ny] = true;
                            q.add(new Node(nx,ny));
                        }
                        
                        for(int j=0; j<=25; j++) {
                            if(gate[j].size()!=0 && key[j]) {
                                for(int k=0; k<gate[j].size(); k++) {
                                    Node tmp= gate[j].get(k);
                                    map[tmp.x][tmp.y] ='.';
                                    visited[tmp.x][tmp.y] = true;
                                    q.add(new Node(tmp.x,tmp.y));
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
 
class Node{
    int x,y;
    Node(int x, int y){
        this.x=x;
        this.y=y;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
>cs