반응형

문제 출처 :


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



알고리즘 분석 :


문제 해결에 필요한 사항

1. BFS


이 문제를 풀기 전, [4179번] Fire! :: http://www.crocus.co.kr/714를 풀고 이 문제를 풀기를 권장한다.


위의 문제와 아에 똑같은 문제인데 이번 문제는 테스트 케이스가 존재하는 것만 다르다.


이전 게시물과 동일하게 두번의 BFS로 해결한다.


첫번째는 불길이 각 위치에 도달하는 시간을 visit[][]에 표시해 줌으로써 불의 시간정보를 표시해주고


두번째는 상근이가 움직이는데 불보다 빠르게 움직이는지 느리게 움직이는지 BFS로 판단해주면 된다.


불이 났다면 find = false, 불이 나지 않았다면 find = true로 해결한다.



소스 코드 : 


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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#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 main()
{
    int tCase;
    scanf("%d"&tCase);
    
    while (tCase--)
    {
        int n, m;
        int jx, jy;
        queue<INFO> q;
 
        scanf("%d %d"&n, &m);
 
 
        // 맵 입력
        getchar();
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
                scanf("%c"&str[i][j]);
 
            getchar();
        }
 
        for (int i = 0; i <= m + 1; i++)
        {
            str[i][0= '$';
            str[i][n + 1= '$';
        }
 
        for (int j = 0; j <= n + 1; j++)
        {
            str[0][j] = '$';
            str[m + 1][j] = '$';
        }
 
        memset(visit, 0sizeof(visit));
 
        // #이면 visit에는 -1로, @면 상근이의 위치 받아내고, 
        // *이면 불이난 위치의 값을 queue에 넣는다.
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (str[i][j] == '#')
                    visit[i][j] = -1;
 
                else if (str[i][j] == '@')
                {
                    jx = j;
                    jy = i;
                }
                else if (str[i][j] == '*')
                    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;
 
            // . 또는 @는 통행 가능 길
            if (y - >= && !visit[y - 1][x] && (str[y - 1][x] == '.' || str[y - 1][x] == '@'))
                q.push(INFO{ y - 1, x, cnt + });
 
            if (y + <= m && !visit[y + 1][x] && (str[y + 1][x] == '.' || str[y + 1][x] == '@'))
                q.push(INFO{ y + 1, x, cnt + });
 
            if (x - >= && !visit[y][x - 1&& (str[y][x - 1== '.' || str[y][x - 1== '@'))
                q.push(INFO{ y, x - 1, cnt + });
 
            if (x + <= n && !visit[y][x + 1&& (str[y][x + 1== '.' || str[y][x + 1== '@'))
                q.push(INFO{ y, x + 1, cnt + });
        }
    
        // 상근이의 위치와 시간을 넣어준다.
        q.push(INFO{ jy,jx,});
        bool find = false;
 
        while (!q.empty())
        {
            if (find == true)
            {
                q.pop();
                continue;
            }
 
            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\n", cnt);
                find = true;
                continue;
            }
 
            // 불길이 도착한 시간 이상이고, 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 + <= m && (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 + <= n && (visit[y][x + 1> cnt + || visit[y][x + 1== 0))
                q.push(INFO{ y, x + 1, cnt + });
        }
 
        // 큐를 모두 수행할 동안 $를 못만나면 결국 impossible한 것
        if(find == false)
            printf("IMPOSSIBLE\n");
    }
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus



반응형

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

[2252번] 줄 세우기  (0) 2017.03.31
[2623번] 음악프로그램  (0) 2017.03.31
[4179번] Fire!  (4) 2017.03.31
[11780번] 플로이드 2  (0) 2017.03.30
[1168번] 조세퍼스 문제 2  (0) 2017.03.29