Problem Solving/BOJ

[백준 1194번] [BFS / 비트마스킹] 달이 차오른다, 가자.

  • -
728x90
반응형

Approach

문제에서 이동 횟수의 최솟값을 묻는 상황이므로, BFS를 바로 떠올려주면 된다.

다만, 이 문제에서 되게 독특한 지점은 각 이동하는 상황에서 키를 가지고 있는지 여부가 굉장히 중요하다. 따라서 키를 가지고 있는지 여부를 set으로 넘겨줘도 되지만, 비트마스킹을 활용해주면 숫자 하나로 모든 것을 판단할 수 있게 된다.

 

추가적으로 visited도 신경써야 하는데, 키가 달라진다면 기존에 방문했던 곳이라도 양상이 달라질 수 있기 때문에 visited를 3차원으로 잡아주면 된다. 다음 문제와 비슷하게 느낌을 받았으면 충분하다. (위 문제도 단순히 같은 위치를 방문한다고 해서 같은 의미는 아니므로 차원을 1개 늘렸다.)

https://viyoung.tistory.com/334

 

[백준 2206번] [BFS] 벽 부수고 이동하기

Approach 표면적으로 보면 BFS 대표 유형과 유사해보인다. 다만, 일반적인 문제와 달리 1칸 벽을 뚫을 수 있다는 측면을 추가적으로 고려해야한다는 점에서 어렵다고 할 수 있다. 잘 생각해보면, 무

viyoung.tistory.com

 

추가적으로 구현 과정에서 UTF-8의 성질을 이용하면 조금 더 쉽게 키와 문을 매핑지을 수 있다.

Code

#include <bits/stdc++.h>
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)

using namespace std;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;
int n, m;
pii start_point;

int move_x[4] = {-1, 1, 0, 0};
int move_y[4] = {0, 0, -1, 1};
char r[50][50];
bool visited[50][50][1 << 6];

int main(void){
    fastio;
    memset(visited, 0, sizeof(visited));
    set<pii> end_point;
    cin >> n >> m;
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            cin >> r[i][j];
            if(r[i][j] == '0'){
                start_point = make_pair(i, j);
            }
            else if(r[i][j] == '1'){
                end_point.insert(make_pair(i, j));
            }
        }
    }

    queue<piii> q;
    q.push(make_pair(start_point, 0));
    visited[start_point.first][start_point.second][0] = 1;
    int move_num = 0;
    while(!q.empty()){
        int q_size = q.size();
        for(int i = 0; i < q_size; i++){
            int x = q.front().first.first;
            int y = q.front().first.second;
            int key = q.front().second;
            if(end_point.find(q.front().first) != end_point.end()){
                cout << move_num << "\n";
                return 0;
            }
            q.pop();
            for(int j = 0; j < 4; j++){
                int dx = x + move_x[j];
                int dy = y + move_y[j];
                if(dx < 0 || dx >= n || dy < 0 || dy >= m) continue;
                else{
                    if(!visited[dx][dy][key]){
                        if(r[dx][dy] == '.' || r[dx][dy] == '1' || r[dx][dy] == '0'){
                            q.push(make_pair(make_pair(dx, dy), key));
                            visited[dx][dy][key] = 1;
                        }
                        else if(r[dx][dy] == '#') continue;
                        else if (r[dx][dy] >= 'a' && r[dx][dy] <= 'f'){
                            int to = key | (1 << (r[dx][dy] - 'a'));
                            q.push(make_pair(make_pair(dx, dy), to));
                            visited[dx][dy][to] = 1;
                        }
                        else if(r[dx][dy] >= 'A' && r[dx][dy] <= 'F'){
                            if(key & (1 << (r[dx][dy] - 'A'))){
                                q.push(make_pair(make_pair(dx, dy), key));
                                visited[dx][dy][key] = 1;
                            }
                        }

                    }
                }
            }
        }
        move_num++;
    }

    cout << -1 << "\n";
    return 0;
}
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.