문제 풀이

[SWEA] 1953 탈주범 검거

컴영 2020. 5. 8. 18:51

1953 탈주범 검거


풀이)

bfs를 이용해 탈주범이 이동하게 푼 문제이다


핵심은

각 터널마다 어떤 방향(상하좌우)로 움직일 수 있는지,

방향으로 움직였을때 움직인 방향의 터널과 연결될 수 있는지를 저장해놓는 것이다.


나같은 경우는 

터널 구조물 1~7번 각각 어떤 방향으로 움직이는지를 vector <int> turner[8];에 저장하고

방향으로 움직였을때 터널에 이어질 수 있는 지를 vector <int> connect[4];에 저장했다.


turner[i] = i번째 터널일 경우 어떤 방향으로 움직일 수 있는지


상하좌우를 0, 1, 2, 3 이라고 할때

터널 구조물 1은 (십자가 모양) : 0, 1, 2, 3 방향 모두 움직일 수 있다.

터널 구조물 2는 (세로막대기 모양) : 0, 1 방향으로만 움직일 수 있다.

...

이런식으로 생각해 vector에 저장해놓았다.

결과물

vector <int> turner[8] = { {},{0,1,2,3},{0,1},{2,3},{0,3},{1,3},{1,2},{0,2} }; //터널은 1번부터 시작하니깐 0번은 빈공간으로 둠


그리고 현재 터널에서 다음 칸의 터널로 움직일때,

터널이 연결되어야 이동 가능하므로


connect[i] = i방향으로 움직여서 갈때, 다음 칸의 터널이 뭐여야 하는지 


예를 들어 

현재 터널이 2번(세로막대기 모양)이면 움직일 수 있는 방향은 상 하 이다.

그럼 으로 갔을 때 연결될 수 있는 터널은


 이런식으로 1번터널, 5번터널, 6번터널이다.


이런식으로 생각해          상[0]      하[1]       좌[2]         우[3]        로 갈때 어떤 터널과 연결될 수 있는지 저장했다.

결과물

vector <int> connect[4] = { {1,2,5,6},{1,2,4,7},{1,3,4,5},{1,3,6,7} }; 



따라서,

이들을 이용해

1. 현재 좌표 어떤 터널인지

2. 그 터널에서는 어떤 방향(상하좌우)으로 갈 수 있는지

3. 각 방향으로 갈 수 있는 지(다음 칸 터널 확인)


를 반복해, 갈 수 있는 지점을 세어주면 결과가 나온다.


코드)


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
#include <stdio.h>
#include <queue>
#include <string.h>
#include <vector>
using namespace std;
 
int n,m,r,c,l;
int map[50][50];
bool visited[50][50];
//상하좌우 0123
int dy[4= { -1,1,0,0 };
int dx[4= { 0,0,-1,1 };
 
vector <int> turner[8= { {},{0,1,2,3},{0,1},{2,3},{0,3},{1,3},{1,2},{0,2} };
vector <int> connect[4= { {1,2,5,6},{1,2,4,7},{1,3,4,5},{1,3,6,7} };
int bfs(int time) {
    int cnt = 1;//갈수 있는 위치개수
    visited[r][c] = true;
    queue <pair<intint>> qu;
    qu.push({ r,c });
    while (!qu.empty())
    {
        int size = qu.size();
        while (size--)
        {
            int y = qu.front().first;
            int x = qu.front().second;
            int t = map[y][x];//현재 터널
            qu.pop();
            for (int i = 0; i < turnel[t].size(); i++) {
                int dir = turner[t][i];
                int ny = y + dy[dir];
                int nx = x + dx[dir];
                if (ny >= 0 && ny < n && nx >= 0 && nx < m) {
                    //이미 방문 터널 or 터널이 없는곳
                    if (visited[ny][nx] || map[ny][nx] == 0continue;
                    //이동해온 방향과 다음 터널과 연결될수있는지
                    bool fail = true;
                    for (int j = 0; j < 4; j++) {
                        if (connect[dir][j] == map[ny][nx]) {
                            fail = false;
                            break;
                        }
                    }
                    if (fail) continue;
                    visited[ny][nx] = true;
                    cnt++;
                    qu.push({ ny,nx });
                }
            }
        }
        time--;
        if (time == 1break;
    }
    memset(visited, falsesizeof(visited));
    return cnt;
}
 
int main() {
    freopen("sample_input (1).txt""r", stdin);
    int T = 0;
    scanf("%d"&T);
    for (int test_case = 1; test_case <= T; test_case++) {
        scanf("%d %d %d %d %d"&n, &m, &r, &c, &l);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                scanf("%d"&map[i][j]);
            }
        }
        if (l == 1) {
            printf("#%d 1\n", test_case);
        }
        else {
            printf("#%d %d\n", test_case, bfs(l));
        }
        
    }
 
    return 0;
}
cs