이 문제는 BFS 를 이용해 푸는 미로 문제의 응용버전이라고 볼 수 있다.

이 문제만의 특징은 'A'~'F' 의 문이 있고, 문을 열기 위해선 각 알파벳에 맞는 소문자 'a'~'f' 열쇠를 가지고 있으면 통과할 수 있다.

 

다행히 문과 열쇠의 종류가 6개 밖에 안되기 때문에, 비트마스크를 이용해 저장할 수 있고

주의할 점은 지나온 길을 다시 가지 않기 위한 visited 변수는 키의 보유 상황에 따라 갈 수 있는 길이 다르기 때문에 이를 고려해야한다.

 

 

 

 

 소스코드

 

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
#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
 
int n,m, sy,sx, dy[4= {-1,1,0,0}, dx[4= {0,0,-1,1};
char map[55][55];
int visited[55][55][66];
 
struct cell {
    int y, x, step, keys;    
    cell(int y, int x, int step, int keys) : y(y), x(x), step(step), keys(keys) { }
};
 
bool check_next_step(int y,int x, int keys){
    if (map[y][x] >= 'A' && map[y][x] <= 'F'){
        return keys & (1<<map[y][x] - 'A');
    } else {
        return map[y][x] != '#';
    }
}
 
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        scanf("%s",map[i]);
        for(int j=0;j<m;j++){
            if(map[i][j] == '0'){
                sy=i, sx=j;
            }
        }
    }
    queue < cell > q;
    q.push(cell(sy,sx, 00));
    visited[sy][sx][0= true;
    int ans = -1;
    while(!q.empty()){
        cell cur = q.front(); q.pop();        
        if(map[cur.y][cur.x] == '1') {
            ans = cur.step;
            break;
        }
        if (map[cur.y][cur.x] >='a' && map[cur.y][cur.x] <='f') {
            cur.keys |= (1<< (map[cur.y][cur.x] - 'a'));
        }        
        for(int i=0;i<4;i++){
            int ny = cur.y + dy[i], nx = cur.x + dx[i];
            if(nx>=0 && ny >=0 && nx < m && ny < n && !visited[ny][nx][cur.keys]){
                if(check_next_step(ny,nx, cur.keys)) {
                    visited[ny][nx][cur.keys] = true;
                    q.push(cell(ny, nx, cur.step+1, cur.keys));
                }
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}
 
cs

 

 

'알고리즘 문제풀이' 카테고리의 다른 글

BOJ 15649~15650 N과 M  (0) 2020.08.20
BOJ 2580 스도쿠  (0) 2020.08.20
BOJ 6087 레이저통신  (0) 2020.08.09
BOJ 11505 구간 곱 구하기  (0) 2020.08.06
1344 축구  (0) 2018.06.01

+ Recent posts