백준 9328 열쇠
본문 바로가기
알고리즘 모음집/알고리즘 (Algorithm)

백준 9328 열쇠

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

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

 

9328번: 열쇠

문제 상근이는 1층 빌딩에 침입해 매우 중요한 문서를 훔쳐오려고 한다. 상근이가 가지고 있는 평면도에는 문서의 위치가 모두 나타나 있다. 빌딩의 문은 모두 잠겨있기 때문에, 문을 열려면 열쇠가 필요하다. 상근이는 일부 열쇠를 이미 가지고 있고, 일부 열쇠는 빌딩의 바닥에 놓여져 있다. 상근이가 훔칠 수 있는 문서의 최대 개수를 구하는 프로그램을 작성하시오. 입력 첫째 줄에 테스트 케이스의 개수가 주어진다. 테스트 케이스의 수는 100개를 넘지 않는다. 각

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include<stdio.h>
#include<queue>
#include<vector>
#define NSIZE 104
#define MSIZE 104
using namespace std;
char input[NSIZE][MSIZE];
int N, M;
int ret;
int dy[] = { 0,1,0,-1 };
int dx[] = { 1,0,-1,0 };
struct Data {
    int y, x;
};
vector<Data>pos;
int Alpha[26];
int chk[NSIZE][MSIZE];
void init() {
    ret = 0;
    pos.clear();
    memset(Alpha, 0sizeof(Alpha));
    memset(input, 0sizeof(input));
    memset(chk, 0sizeof(chk));
 
    scanf("%d %d"&N, &M);
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            scanf(" %1c"&input[i][j]);
        }
    }
    char arr[26];
 
    scanf("%s", arr);
    if (arr[0== '0')return;
    for (int i = 0; arr[i] != NULL; i++) {
        Alpha[arr[i] - 'a'= 1;
    }
}
void bfs() {
        queue<Data>q;
        queue<Data>door[26];
        memset(chk, 0sizeof(chk));
        q.push({ 0,0 }); chk[0][0= 1;
        while (!q.empty()) {
            Data c = q.front(); q.pop();
            for (int dir = 0; dir < 4; dir++) {
                Data n;
                n.y = c.y + dy[dir];
                n.x = c.x + dx[dir];
                if (0 <= n.y&&n.y <= N + 1 && 0 <= n.x&&n.x <= M + 1) {
 
                    if (input[n.y][n.x] != '*'&&chk[n.y][n.x] == 0) {
                        chk[n.y][n.x] = 1;
                        if ('A' <= input[n.y][n.x] && input[n.y][n.x] <= 'Z') {
                            if (Alpha[input[n.y][n.x] - 'A'])q.push({ n.y,n.x });
                            else door[input[n.y][n.x] - 'A'].push({ n.y,n.x });
                        }
 
                        else if ('a' <= input[n.y][n.x] && input[n.y][n.x] <= 'z') {
                            q.push({ n.y,n.x });
                            if (!Alpha[input[n.y][n.x] - 'a']) {
                                Alpha[input[n.y][n.x] - 'a'= 1;
                                while (!door[input[n.y][n.x] - 'a'].empty()) {
                                    q.push({ door[input[n.y][n.x] - 'a'].front() }); door[input[n.y][n.x] - 'a'].pop();
                                }
                            }
                        }
                        else {
                            q.push({ n.y,n.x });
                            if (input[n.y][n.x] == '$')ret++;
                        }
                    }
                }
            }
        }
}
int main(void) {
    int T = 0;
    scanf("%d"&T);
    for (int t = 1; t <= T; ++t) {
        //printf("%d", ret);
 
        init();
        bfs();
        printf("%d\n", ret);
    }
    return 0;
}
]
 

이문제는 처음에는 생각했을때 문위치에서 다시 시작을 해야 열쇠가 있을때 그 부분까지 들어가겠다 생각은 했지만 

처음 생각했던 방식인 열쇠를 얻을수 있는 경우 일단 열쇠를 다찾고 찾은 열쇠로 처음부터 다시 큐를 돌자 생각했었는데

그렇게 했다가는 시간초과가 생길 것 같아서 포기하고 그냥 큐안에 큐를 돌리자 생각을 했습니다.

뭐라고 ? 큐안에 큐 이게 무슨 소리냐 하시는 분들이 있을수 있습니다. 현재 여기서 문위치에서 큐를 또 이동이 

되어야 갈 수있는 곳은 다갈수 있게 되는데 상근이가 이동시 갈수있는 문을 큐배열을 만들어 넣는다는 것입니다.

문은 대문자 A - 대문자 Z 이므로  초 26 개를 queue<Data> door[26];   이렇게 만들어놓고

그 위치에 문이 있고 열수있는  열쇠가 있을때 기존에 돌아가는 큐에 넣으면 우리가 생각했던대로 상근이가 이동해서

문서를 훔쳐 올수 있습니다.

 

나쁜짓을 도와줘서 문제 풀기 싫다는 분도 있을 수 있지만 그래도 풀어봅시다.

 

Alpha[input[n.y][n.x] - 'A'

Alpha[input[n.y][n.x] - 'a'

이렇게 하신걸 볼수 있는데 이것은 0인 인덱스 를 만들기위함 0인 인덱스보다는 숫자인 인덱스로 생각하겠다가 맞는

표현 같네요.

알파벳을 만나면 대문자는  A가 65 이므로  B는 아스키코드가66 이렇게 한개씩증가합니다.

그럼 이걸 배열 인덱스로 그냥 쓴다 생각해봅시다

그럼  arr[A] == arr[65] 랑 같다고 생각하시면 됩니다. 그럼 0부터 64인 공간은 낭비죠?

그렇지 않기위해서 0으로 만들어주기위해 즉 0 부터 1 ~... 이렇게 받기위해 -'A'를 빼서쓰는것이죠,

 소문자 a도 같은 의미입니다.

저는 처음 C언어 소스를 봤을때 저렇게 짠사람은 비상하다 정말 신적인 존재라 생각을 했었을때가 있는데 그냥 쓰시다 

보면 당연히 저렇게 해야구나 체득하시게 되는 날있습니다. 제가 저것을 안다고해서 알고리즘 마스터는 아니지만 

처음 에는 그렇게 생각이 들더군요 .

 

열쇠를 찾았을때 그때 문 위치부터 시작하게 왜 큐에 넣는지 그림으로 설명하자면 이렇습니다.

저렇게 큐배열에 이미 상근이가 문앞에 있는경우를 저장해놓고 문을 열 수 있는 열쇠가 생기면 그 경우도 상근이가

이동을 해야하므로 저렇게 열쇠를 따고 그것을 큐에 넣어주면 그위치에서 상하좌우 또 갈 수있게 해주는것이죠.

 

저렇게 보시니 쉽나요? 사실 제설명이 완벽한 소스가 아니라 어려우실수 있지만 이렇게도 

풀수 있으니 한번 도전해보세요.

오늘은 여기까지이고 언제나 즐거운 코딩하세요.

 

728x90
반응형

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

백준 16637 괄호 추가하기  (0) 2019.09.22
백준 16509 장군  (0) 2019.09.21
백준 6087 레이저 통신  (0) 2019.09.19
백준 16918 봄버맨  (0) 2019.09.17
백준 9019 DSLR  (0) 2019.09.17

댓글