백준 1194 달이 차오른다, 가자.
본문 바로가기
알고리즘 모음집/알고리즘 (Algorithm)

백준 1194 달이 차오른다, 가자.

by KyeongMin 2019. 9. 25.
728x90
반응형

https://www.acmicpc.net/problem/1194

 

1194번: 달이 차오른다, 가자.

첫째 줄에 미로의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 50) 둘째 줄부터 N개의 줄에 미로의 모양이 주어진다. 같은 타입의 열쇠가 여러 개 있을 수 있고, 문도 마찬가지이다. 그리고, 영식이가 열쇠를 숨겨놓는 다면 문에 대응하는 열쇠가 없을 수도 있다. 0은 한 개, 1은 적어도 한 개 있다. 그리고, 열쇠는 여러 번 사용할 수 있다.

www.acmicpc.net

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
#include<stdio.h>
#include<queue>
#define NSIZE 50
#define MSIZE 50
using namespace std;
int N, M;
char input[NSIZE][MSIZE];
int chk[NSIZE][MSIZE][64];
int dy[] = { 0,1,0,-1 };
int dx[] = { 1,0,-1,0 };
struct Data {
    int y, x, cnt, key;
};
queue<Data>q;
void init() {
    scanf("%d %d"&N, &M);
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            scanf(" %1c"&input[i][j]);
            if (input[i][j] == '0') {
                q.push({ i,j,0,0 });
                chk[i][j][0= 1;
            }
        }
    }
}
void bfs() {
    while (!q.empty()) {
        Data c = q.front(); q.pop();
        if (input[c.y][c.x] == '1') {// 탈출 가능
            printf("%d\n", c.cnt);
            return;
        }
        for (int dir = 0; dir < 4; dir++) {
            Data n;
            n.y = c.y + dy[dir];
            n.x = c.x + dx[dir];
            n.cnt = c.cnt + 1;
            n.key = c.key;
            if (0 <= n.y&&n.y < N && 0 <= n.x&&n.x < M) {
                if (chk[n.y][n.x][n.key] == 0 && input[n.y][n.x] != '#') {
                    chk[n.y][n.x][n.key] = 1;
                    if ('A' <= input[n.y][n.x] && input[n.y][n.x] <= 'F') {
                        if (n.key & 1 << input[n.y][n.x] - 'A') {//키가 있는경우
                            q.push(n);
                        }        
                    }
                    else if ('a' <= input[n.y][n.x] && input[n.y][n.x] <= 'f') {
                        n.key = n.key | 1 << input[n.y][n.x] - 'a';
                        
                        q.push(n);
                    }
                    else {
                        q.push(n);
                    }
                }
            }
        }
    }
    printf("-1\n");
}
int main(void) {
    init();
    bfs();
    return 0;
}
 
 

이 문제를 어떻게 해서 풀까하다가 따로 키를 저장하면서 움직이고 그렇고 해서 그냥

비트마스크를 공부해서 풀었습니다.

비트 마스크가 뭐냐 하시는 분들이 있는데 진짜 말만 거창하지 아무것도 아닌데 저도 사실 

지금까지 어려워 보여서 안했는데  이번문제는 비트마스크로 해야 답이 날 것 같아서 비트마스크를 적용 했는데

 

본론은 우선  a부터 f까지 키가 있는데 

비트로 연산을 하더라도 키를 전부 가지고 있을떄의 정수는 63이므로 배열을 

이렇게 지정을 해주었고

위와 같이 키를 가지게 할때는 OR 연산자인 |  이걸로 하고 

문을 열수 있는 열쇠가 있는지 확인 하기 위해서 는 &  AND 연산자로 해주어야 키로 문을 열수 있습니다.

왜냐하면 

이 식이 문을 열수 있는 지 없는지 확인 하는 경우 인데

우선 키가 f만 가지고 있으면 현재 

 n.key는 1 0 0 0 0 0 비트이므로 32를 현재 n.key 가 가지고 있고 

현제 inpt[n.y][n.x]==F 라면 1<< 시프트 했을때 1 0 0 0 0 0 이므로

1 0 0 0 0 0

1 0 0 0 0 0

를 AND 연산 해주면 1 이기때문에 참이 됨으로 큐에 문이 열렸으니 넣을 수 있는 것입니다.

AND 연산은 

0 0 1

0 1 0

1 0 0

1 1 1

이라는 조건을 가지고 있기때문입니다. 무슨 소리냐 하시는 분들은  & 와 | 연산하는법을 참조해주시면

도움이 많이 될듯 합니다. 이렇게만해서 키가 있으면 문을 열고 그위치를 큐에 넣기만 하면 알아서 하기떄문에 

그냥 bfs와 별 다를바 없어지죠?

저도 처음에는 이해를 못한것은 아니지만 그냥 안하다보니 하기 싫었는데  진짜 해보니 별거 아니더라구요.

여러분들은 더 똑똑하시고 잘하시니까 더 잘 이해하고 잘하실꺼라 생각합니다.

오늘은 여기까지이고 다음주도 좋은 자료가지고 돌아오겠습니다. 이상 입니다. 

 

 

 

728x90
반응형

'알고리즘 모음집 > 알고리즘 (Algorithm)' 카테고리의 다른 글

백준 1260 DFS와 BFS  (0) 2019.09.29
백준 15662 톱니바퀴(2)  (0) 2019.09.29
백준 1600 말이 되고픈 원숭이  (0) 2019.09.23
백준 16637 괄호 추가하기  (0) 2019.09.22
백준 16509 장군  (0) 2019.09.21

댓글