Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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
Tags
more
Archives
Today
Total
관리 메뉴

대웅짱님의 블로그

[9328] 열쇠 본문

알고리즘/BOJ

[9328] 열쇠

대웅짱 2018. 7. 10. 21:21

문제: https://www.acmicpc.net/problem/9328


주어진 정보로 상근이가 몇 개의 문서를 훔칠 수 있는지를 묻는 문제이다.


그래프 탐색문제이므로 BFS로 풀면 되지만 문제가 까다롭다.


바로 열쇠를 획득했을 때 이전에 탐색했던 문을 다시 찾아가 열고 또 계속해서 탐색을 진행할 수 있다는 점이었는데


처음에 문제를 풀 때는 너무 일차원적으로 생각해서


그냥 열쇠를 획득하면 빌딩 입구(테두리 중에서 '*'이 아닌 곳)들을 다시 처음부터 탐색을 진행했다.


즉 빌딩 입구들을 벡터에 다 넣어놓고 for문을 돌면서 각 입구마다 bfs를 진행하고


bfs진행중 열쇠를 만나면 그 열쇠지점을 '.'으로 바꾸고 for문을 다시 처음부터 수행하도록 했었는데


이렇게 하니까 시간이 무려 900ms가 넘었다. 예제가 조금만 더러워도 시간초과가 날거같아서


다시 풀었다.


열쇠를 찾아서 문제가 생기는 지점은 바로 문이다.


그러므로 bfs진행 중 만나는 문들 중 현재 나에게 열쇠가 있는 문이면 '.'로 바꿔주고


만약 현재 못여는 문이라면 벡터에 저장해둔다.


그 후 bfs탐색 중 열쇠를 찾게되면 벡터에 넣어놨던 좌표 중 현재 열쇠로 열 수 있는 문 좌표를 bfs의 시작 정점으로 큐에 넣어준다.


이렇게 하면 bfs 시작 정점으로 문 차례가 되었을 때 문 까지 가는 통로는 visit으로 처리되어 있으므로 문 너머를 탐색하게 된다.


다만 함정이 하나 있는데


문은 하나가 아니라 여러개일 수 있으므로


각 문에 해당하는 벡터를 다 따로 만들어서 관리해 줘야 한다.  간단하게 이차원 벡터를 만들어 주면 된다.




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
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<iostream>
using namespace std;
char arr[110][110];
bool visit[110][110];
int key[26];
int dx[4= { 00-11 };
int dy[4= { 1-100 };
int n, m;
 
int bfs(queue<pair<intint> > qu) {
    vector< pair<intint> > vt[26];
    int cnt = 0;
    while (int s = (int)qu.size()) {
        while (s--) {
            int cx = qu.front().first;
            int cy = qu.front().second;
            qu.pop();
 
            if (arr[cx][cy] == '$') {
                arr[cx][cy] = '.';
                cnt++;
            }
            else if (arr[cx][cy] >= 'a' && arr[cx][cy] <= 'z') {
                if (!vt[arr[cx][cy]-'a'].empty()) {
                    for (int i = 0; i < (int)vt[arr[cx][cy] - 'a'].size(); i++) {
                        int vx = vt[arr[cx][cy] - 'a'][i].first;
                        int vy = vt[arr[cx][cy] - 'a'][i].second;
                        qu.push({ vx, vy });
                    }
                    vt[arr[cx][cy] - 'a'].clear();
                }
                key[arr[cx][cy] - 'a'= 1;
                arr[cx][cy] = '.';
            }
            else if (arr[cx][cy] >= 'A' && arr[cx][cy] <= 'Z') {
                if (key[arr[cx][cy] - 'A'])
                    arr[cx][cy] = '.';
                else {
                    vt[arr[cx][cy] - 'A'].push_back({ cx, cy });
                    continue;
                }
            }
 
            for (int i = 0; i < 4; i++) {
                int nx = dx[i] + cx;
                int ny = dy[i] + cy;
 
                if (nx < 0 || nx >= n || ny < 0 || ny >= m || visit[nx][ny] ||
                    arr[nx][ny] == '*'continue;
                visit[nx][ny] = 1;
                qu.push({ nx, ny });
            }
 
        }
    }
    return cnt;
}
 
 
int main() {
    int t;
    scanf("%d"&t);
    while (t--) {
        memset(arr, 0sizeof(arr));
        memset(key, 0sizeof(key));
        memset(visit, 0sizeof(visit));
        scanf("%d %d"&n, &m);
        queue<pair<intint> >qu;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                scanf(" %1c"&arr[i][j]);
                if (i == 0 || i == n - 1 || j == 0 || j == m - 1) {
                    if (arr[i][j] != '*') qu.push({ i, j });
                }
            }
        }
        string str;
        cin >> str;
        for (int i = 0; i < (int)str.size(); i++) {
            if (str[i] == '0'break;
            key[str[i] - 'a'= 1;
        }
        int res = bfs(qu);
 
        printf("%d\n", res);
    }
}
cs






'알고리즘 > BOJ' 카테고리의 다른 글

[12100] 2048 (Easy)  (0) 2019.02.07
[13460] 구슬 탈출 2  (0) 2019.01.29
[4991] 로봇 청소기  (0) 2018.07.05
[5427] 불  (0) 2018.07.04
[2146] 다리 만들기  (0) 2018.07.04