1일1알

Judge - 1170 : 크리스마스의 요정 C++ 본문

알고리즘

Judge - 1170 : 크리스마스의 요정 C++

영춘권의달인 2022. 7. 14. 13:37

출처 : https://judge.koreatech.ac.kr/problem.php?id=1170

 

어떤 열쇠들을 가지고 있는지를 비트로 관리하고 비트마다 방문 확인을 따로 하여 bfs로 풀었다.

 

#include <iostream>
#include <string>
#include <vector>
#include <math.h>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <math.h>
#include <set>
#include <map>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <iomanip>
#include <limits.h>

using namespace std;
using int64 = long long;

const int SIZE = 'f' - 'a' + 1;

int dRow[4] = { -1,0,1,0 };
int dCol[4] = { 0,1,0,-1 };

struct Info {
    int row;
    int col;
    int moveCnt;
    int keyBit;
};

int keyBits[SIZE];

vector<vector<char>> board;
vector<vector<vector<bool>>> found;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    for (int i = 0; i < SIZE; i++) {
        keyBits[i] = 1 << i;
    }

    int t;
    cin >> t;
    while (t--) {

        int keySum = 0;

        int w, h;
        cin >> w >> h;
        board = vector<vector<char>>(h, vector<char>(w));
        found = vector<vector<vector<bool>>>(pow(2, SIZE), vector<vector<bool>>(h, vector<bool>(w, false)));
        
        pair<int, int> start;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                cin >> board[i][j];
                if (board[i][j] == '?')
                    start = { i,j };
                if (board[i][j] >= 'a' && board[i][j] <= 'f')
                    keySum += keyBits[board[i][j] - 'a'];
            }
        }

        queue<Info> q;
        q.push({ start.first,start.second,0,0 });
        found[0][start.first][start.second] = true;

        bool isPossible = false;

        while (!q.empty()) {
            auto curr = q.front();
            q.pop();

            if (curr.keyBit == keySum) {
                isPossible = true;
                cout << curr.moveCnt << "\n";
                break;
            }

            for (int i = 0; i < 4; i++) {
                int nextRow = curr.row + dRow[i];
                int nextCol = curr.col + dCol[i];
                int nextKeyBit = curr.keyBit;
                if (nextRow < 0 || nextRow >= h) continue;
                if (nextCol < 0 || nextCol >= w) continue;
                if (board[nextRow][nextCol] == '$') continue;
                if (found[curr.keyBit][nextRow][nextCol]) continue;
                if (board[nextRow][nextCol] >= 'A' && board[nextRow][nextCol] <= 'F') {
                    if ((curr.keyBit & keyBits[board[nextRow][nextCol] - 'A']) == 0)
                        continue;
                }
                if (board[nextRow][nextCol] >= 'a' && board[nextRow][nextCol] <= 'f') {
                    nextKeyBit = curr.keyBit | keyBits[board[nextRow][nextCol] - 'a'];
                }
                q.push({ nextRow,nextCol,curr.moveCnt + 1,nextKeyBit });
                found[nextKeyBit][nextRow][nextCol] = true;
            }
        }

        if (!isPossible)
            cout << "-1" << "\n";
    }
}