열쇠(BOJ9328)

2024. 11. 20. 16:10BOJ/BFS,DFS

문제

이미지 클릭

문제 설명

  • 기본적으로 맵의 구성은 다음과 같이 설명할 수 있다.
'.' :이동 가능한 빈 공간
'*': 이동 불가능한 벽
'$': 훔쳐야 하는 문서
알파벳 대문자: 문
알파벳 소문자: 열쇠(알파벳 대문자와 동일 문자일 경우 가능(a열쇠는 A문에서 가능))
  • 맵이 주어진 다음에는 일련의 문자열이 주어지는데 이는 이미 가지고 있는 열쇠를 의미한다.
  • 만약 0이 주어진다면 초기에 가지고 있는 열쇠는 없다.
cz: c와 z열쇠를 가지고 있음
0: 열쇠 없음
  • 맵이 주어졌을 때 총 몇 개의 문서를 훔칠 수 있을지 알아내야 한다.

문제 해설

  • bfs
일단 정점을 돌아보면서 다음과 같은 경우의 수를 모두 확인해 준다.
1. '.'인 경우: 그냥 이동
2. '$'인 경우: 문서의 개수를 +1해 주고 그 위치를 '.'으로 변경해 준다.
3. 대문자 알파벳인 경우: 열쇠가 있는 경우에는 그 위치로 이동해 준다.
4. 소문자 알파벳인 경우
-일단 열쇠가 없다면 열쇠를 체크해 주고, 현재까지 이동하면서 방문처리해 준 배열을 초기화해준다.(방문처리하면서 현제 열쇠와 알맞은 문을 방문했을 수도 있음)
-그리고 queue를 초기화해 주고 현제 위치부터 다시 탐색을 시작해 줌.
  • 위의 부분만 만족해 주면서 bfs탐색을 해주면 깔끔하게 가능하다.

최종코드

#include <bits/stdc++.h>
using namespace std;
int t;
const int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
int main() {
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin >> t;
    while (t--) {
        int n, m;
        cin >> n >> m;
        vector<bool> key(30, 0); #키 a~z를 0~25로 저장해준다.
        vector<vector<char>> c(n + 4, vector<char>(m + 4, '.'));
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                cin >> c[i][j];
            }
        }
        string s;
        cin >> s;
        if (s != "0") for (auto i : s) key[i - 'a'] = 1; 
        queue<pair<int, int>> q;
        vector<vector<int>> visited(n + 2, vector<int>(m + 2, 0)); 
        #건물 외부로도 이동가능하기 때문에 크기를 n+2, m+2로 설정해준다.
        q.push({0, 0}); 
        visited[0][0] = 1;
        int cnt = 0; #훔친문서의 개수
        while (!q.empty()) {
            int x = q.front().first, y = q.front().second;
            q.pop();
            for (int i = 0; i < 4; i++) {
                int xx = x + dx[i], yy = y + dy[i];
                if (xx >= 0 && yy >= 0 && xx <= n + 1 && yy <= m + 1 && !visited[xx][yy]) {
                    char cell = c[xx][yy];
                    if (cell == '*') continue;
                    visited[xx][yy] = 1;
                    if (cell == '.') { #빈칸이면 이동한다.
                        q.push({xx, yy}); 
                    } else if (cell == '$') {
                    #문서가 있으면 cnt+=1 해주고 현제 위치는 '.'으로 바꿔줌
                        cnt+=1;    
                        c[xx][yy] = '.'; 
                        q.push({xx, yy});
                    } else if (cell >= 'A' && cell <= 'Z') {
                        if (key[cell - 'A']) {
                        #현제 위치가 문이고 열쇠가 있다면 이동한다.
                            q.push({xx, yy});
                        }
                    } else if (cell >= 'a' && cell <= 'z') { 
                        if (!key[cell - 'a']) {
                            key[cell - 'a'] = 1; #열쇠 체크
                            fill(visited.begin(), visited.end(), vector<int>(m + 2, 0));
                            q = queue<pair<int, int>>();
                            #방문처리(visited)와 queue를 초기화해준다.
                        }
                        c[xx][yy] = '.';
                        q.push({xx, yy});
                    }
                }
            }
        }
        cout << cnt << "\n"; 
    }
}

이미지 클릭

'BOJ > BFS,DFS' 카테고리의 다른 글

게임(BOJ1103)  (0) 2024.11.21
두 로봇(BOJ15971)  (0) 2024.11.18
섬의 개수(BOJ4943)  (1) 2024.11.16
게리맨더링(BOJ 17471)  (0) 2024.11.15
벽 부수고 이동하기 4  (0) 2024.08.17