짱아의 개발 기록장

백준 9328번. 열쇠(c++) / BFS+비트마스크 본문

Algorithm/Baekjoon

백준 9328번. 열쇠(c++) / BFS+비트마스크

jungahshin 2021. 3. 30. 23:33
반응형

설명 추가 예정

 

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
// 열쇠
#include <string>
#include <queue>
#include <climits>
#include <cstring>
#include <vector>
#include <iostream>
 
using namespace std;
 
int testcase, h, w;
string s, tmp;
char map[105][105];
int visited[105][105= { 0, };
int key = 0// 열쇠 소유 상태(bitmask)
int dx[4= { 00-11 };
int dy[4= { -1100 };
 
bool check(char c) {
    if ('A' <= c && c <= 'Z') {
        if (((1<<(c-'A')) & key) != 0) {
            return true;
        }
    }
 
    return false;
}
 
int move()
{
    // 가장자리 진입
    int ans = 0// 획득할 수 있는 문서의 수
    queue<pair<intint>> q;
 
    for (int i = 0; i <= w + 1; i++) {
        q.push(make_pair(0, i));
        q.push(make_pair(h + 1, i));
    }
 
    for (int i = 1; i <= h; i++) {
        q.push(make_pair(i, 0));
        q.push(make_pair(i, w + 1));
    }
 
    // 안으로 진입
    queue<pair<intint>> door[27]; // 열지 못했던 문을 넣어준다.
    while (!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        visited[x][y] = true;
 
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (1 <= nx && nx <= h && 1 <= ny && ny <= w && !visited[nx][ny]) {
                char c = map[nx][ny];
                if (c == '*'continue;
                if (c == '$') { // 문서
                    visited[nx][ny] = true;
                    ans++;
                    q.push(make_pair(nx, ny));
                } else if (c == '.') { // 빈 공간
                    visited[nx][ny] = true;
                    q.push(make_pair(nx, ny));
                } else if ('a' <= c && c <= 'z') { // 열쇠
                    visited[nx][ny] = true;
                    key |= (1 << (c - 'a'));
                    q.push(make_pair(nx, ny));
 
                    // 이전의 문을 연다.
                    while (!door[c - 'a'].empty()) {
                        int x = door[c - 'a'].front().first;
                        int y = door[c - 'a'].front().second;
                        door[c - 'a'].pop();
                        q.push(make_pair(x, y));
                    }
                } else {
                    if (check(c)) { // 열 수 있는 문
                        visited[nx][ny] = true;
                        q.push(make_pair(nx, ny));
                    } else { // 열 수 없는 문 -> 위치만 저장
                        door[c - 'A'].push(make_pair(nx, ny));
                    }
                }
            }
        }
    }
 
    return ans;
}
 
int main()
{
    vector<int> ans;
    cin >> testcase;
    for (int i = 0; i < testcase; i++) {
        // 초기화
        key = 0;
        memset(visited, 0sizeof(visited));
        
        cin >> h >> w;
        for (int j = 1; j <= h; j++) {
            cin >> s;
            for (int k = 0; k < s.size(); k++) {
                map[j][k+1= s[k];
            }
        }
        cin >> tmp;
        if (tmp != "0") {
            for (int j = 0; j < tmp.size(); j++) {
                key |= (1<<(tmp[j] - 'a') );
            }
        }
 
        ans.push_back(move());
    }
 
    for(int i=0; i<ans.size(); i++){
        cout<<ans[i]<<"\n";
    }
 
    return 0;
}
cs
반응형
Comments