반응형

문제 출처 :


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



알고리즘 분석 :


문제 해결에 필요한 사항

1. BFS


이번 문제를 풀면서 절실히 느낀 것은, 내가 맞다고 느꼈을 때, 틀렸습니다가 몇차례 연속해서 나온다면


머리가 정지되고, 코드가 어디가 잘못된 지 정말 찾기 힘든 것 같다.


visit[y][x]라고 적어야 하는 것을 visit[y-1][x]라고 적어두고 계속 다른 곳을 찾고있어서 이 문제를 10번가량 틀린 것 같다.



이 문제는 불의 시간에 따른 흐름을 먼저 BFS로 입력해주고 그다음 존이 움직이면서 불의 시간과 비교를 해주면 된다.


따라서 불의 BFS 한 번, 존의 BFS 한 번 총 2번의 BFS를 돌려야 한다. 


이 코드의 MAP 구성은 어떻게 되어있냐면


n = 5, m = 4일때


@@@@@

@ #### @

@ #J F# @

@ #.  .# @

@ #.  .# @
@ #.  .# @

@@@@@


이런식으로 구성되어있고 결국 J가 @에 닿는 순간 탈출 할 수 있음을, 그게 아니라면 탈출 할 수 없음을 표현한다.


나머지 내용은 코드의 주석을 통해 기입해 두었다.


소스 코드 : 


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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <string>
 
using namespace std;
 
typedef struct _INFO_
{
    int y;
    int x;
    int cnt;
}INFO;
 
char str[1005][1005];
int visit[1005][1005];
 
int jx, jy;
 
int main()
{
    int n, m;
    queue<INFO> q;
 
    scanf("%d %d"&n, &m);
 
    // 모든 맵을 @로 만든다.
    for (int i = 0; i < 1004; i++)
        for (int j = 0; j < 1004; j++)
            str[i][j] = '@';
 
    // 맵 입력
    getchar();
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
            scanf("%c"&str[i][j]);
    
        getchar();
    }
    
    // #이면 visit에는 -1로, J면 존의 위치 받아내고, 
    // F이면 불이난 위치의 값을 queue에 넣는다.
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (str[i][j] == '#')
                visit[i][j] = -1;
 
            else if (str[i][j] == 'J')
            {
                jx = j;
                jy = i;
            }
            else if (str[i][j] == 'F')
                q.push(INFO{ i,j,});
        }
    }
 
    // 불이 번지는 위치에 걸린 시간을 기입한다.
    while (!q.empty())
    {
        int y = q.front().y;
        int x = q.front().x;
        int cnt = q.front().cnt;
 
        q.pop();
 
        if (visit[y][x])
            continue;
 
        visit[y][x] = cnt;
 
        // . 또는 J는 통행 가능 길
        if (y - >= && !visit[y - 1][x] && (str[y - 1][x] == '.' || str[y - 1][x] == 'J'))
            q.push(INFO{ y - 1, x, cnt + });
 
        if (y + <= n && !visit[y + 1][x] && (str[y + 1][x] == '.' || str[y + 1][x] == 'J'))
            q.push(INFO{ y + 1, x, cnt + });
 
        if (x - >= && !visit[y][x - 1&& (str[y][x - 1== '.' || str[y][x - 1== 'J'))
            q.push(INFO{ y, x - 1, cnt + });
 
        if (x + <= m && !visit[y][x + 1&& (str[y][x + 1== '.' || str[y][x + 1== 'J'))
            q.push(INFO{ y, x + 1, cnt + });
    }
    
    // 존의 위치와 시간을 넣어준다.
    q.push(INFO{ jy,jx,});
 
    while (!q.empty())
    {
        int y = q.front().y;
        int x = q.front().x;
        int cnt = q.front().cnt;
 
        q.pop();
 
        // 존이 @로 왔을 때 탈출했다는 의미
        if (str[y + 1][x] == '@' || str[y - 1][x] == '@' || str[y][x - 1== '@' || str[y][x + 1== '@')
        {
            printf("%d", cnt);
            return 0;
        }
 
        // 불길이 도착한 시간 이상이고, visit[y][x]가 0이 아니면
        // 즉, visit[][] = 0인경우는 불이 번지지 않은 위치를 의미 
        if (visit[y][x] <= cnt && visit[y][x] != 0)
            continue;
 
        // 존의 위치를 -2로 표시
        visit[y][x] = -2;
 
        // 불보다 먼저 존이 왔거나, 그 위치의 visit[][]가 0이면
        if (y - >= && (visit[y - 1][x] > cnt + || visit[y-1][x] == 0))
            q.push(INFO{ y - 1, x, cnt + });
 
        if (y + <= n && (visit[y + 1][x] > cnt + || visit[y + 1][x] == 0))
            q.push(INFO{ y + 1, x, cnt + });
 
        if (x - >= && (visit[y][x - 1> cnt + || visit[y][x - 1== 0))
            q.push(INFO{ y, x - 1, cnt + });
 
        if (x + <= m && (visit[y][x + 1> cnt + || visit[y][x + 1== 0))
            q.push(INFO{ y, x + 1, cnt + });
    }
 
    // 큐를 모두 수행할 동안 @를 못만나면 결국 impossible한 것
    printf("IMPOSSIBLE");
    
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus


반응형

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

[2623번] 음악프로그램  (0) 2017.03.31
[5427번] 불  (0) 2017.03.31
[11780번] 플로이드 2  (0) 2017.03.30
[1168번] 조세퍼스 문제 2  (0) 2017.03.29
[1017번] 소수 쌍  (0) 2017.03.29