Game Develop

[Algorithm] Baekjoon 4179번 : 불! 본문

Algorithm/Baekjoon

[Algorithm] Baekjoon 4179번 : 불!

MaxLevel 2023. 2. 25. 19:01

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

 

4179번: 불!

입력의 첫째 줄에는 공백으로 구분된 두 정수 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1000 이다. R은 미로 행의 개수, C는 열의 개수이다. 다음 입력으로 R줄동안 각각의 미로 행이 주어진다. 각각의 문자

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
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
162
163
164
165
166
167
168
struct Node
{
    int y;
    int x;
};
 
char arr[1001][1001];
int dir[4][2= { {-1,0}, {1,0}, {0,-1}, {0,1} };
int row, col;
bool isEscaped = false;
vector<Node> firePositions;
vector<Node> humanPositions;
vector<Node> candidatePositions;
 
bool checkEdge(int y, int x)
{
    if (y == 0 || y == row - 1)
    {
        return true;
    }
 
    if (x == 0 || x == col - 1)
    {
        return true;
    }
 
    return false;
}
 
void moveJ()
{
    vector<Node> temp;
 
    for (int i = 0; i < humanPositions.size(); ++i)
    {
        int curY = humanPositions[i].y;
        int curX = humanPositions[i].x;
 
        if (arr[curY][curX] == 'F'continue;
 
        for (int j = 0; j < 4++j)
        {
            int nextY = curY + dir[j][0];
            int nextX = curX + dir[j][1];
 
            if (nextY < 0 || nextY == row) continue;
            if (nextX < 0 || nextX == col) continue;
            if (arr[nextY][nextX] == '#'continue;
            if (arr[nextY][nextX] == 'J'continue;
            if (arr[nextY][nextX] == 'F'continue;
 
            arr[nextY][nextX] = 'J';
            temp.push_back({ nextY,nextX });
 
            if (checkEdge(nextY, nextX))
            {
                candidatePositions.push_back({ nextY,nextX });
            }
        }
    }
 
    humanPositions = temp;
}
 
void spreadFire()
{
    vector<Node> temp;
 
    for (int i = 0; i < firePositions.size(); ++i)
    {
        int curY = firePositions[i].y;
        int curX = firePositions[i].x;
 
        for (int j = 0; j < 4++j)
        {
            int nextY = curY + dir[j][0];
            int nextX = curX + dir[j][1];
 
            if (nextY < 0 || nextY == row) continue;
            if (nextX < 0 || nextX == col) continue;
            if (arr[nextY][nextX] == '#'continue;
            if (arr[nextY][nextX] == 'F'continue;
 
            arr[nextY][nextX] = 'F';
            temp.push_back({ nextY,nextX });
        }
    }
 
    firePositions = temp;
}
 
void checkCandidates()
{
    for (int i = 0; i < candidatePositions.size(); ++i)
    {
        int y = candidatePositions[i].y;
        int x = candidatePositions[i].x;
 
        if (arr[y][x] != 'F'
        {
            isEscaped = true;
            return;
        }
    }
 
    candidatePositions.clear();
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
 
    cin >> row >> col;
 
    for (int i = 0; i < row; ++i)
    {
        for (int j = 0; j < col; ++j)
        {
            cin >> arr[i][j];
 
            if (arr[i][j] == 'J')
            {
                humanPositions.push_back({ i,j });
            }
            else if (arr[i][j] == 'F')
            {
                firePositions.push_back({ i,j });
            }
        }
    }
 
    if (checkEdge(humanPositions[0].y, humanPositions[0].x))
    {
        cout << 1;
        return 0;
    }
 
    bool isImpossible = false;
    int count = 0;
 
    while (1)
    {
        if (humanPositions.size() == 0)
        {
            isImpossible = true;
            break;
        }
        
        ++count;
 
        moveJ();
        spreadFire();
        checkCandidates();
 
        if (isEscaped) break;
    }
    
    if (isImpossible)
    {
        cout << "IMPOSSIBLE";
    }
    else
    {
        cout << count + 1;
    }
}
cs

BFS문제인데 queue를 사용한게 아닌 그냥 vector로만 풀어봤다.

일단 순서는 지훈이를 먼저 이동시킨 후(노드를 퍼뜨린 후), 불을 확산시킨다(arr에 그대로 덮어씌워서 반영)

이 떄, 지훈이의 노드를 퍼뜨릴 때 퍼뜨릴 지점이 외각지점, 즉 탈출지점이면 일단 후보벡터에 넣어놓는다.

이렇게 하는 이유는 탈출 할 수 있는 지점이더라도 다음 불을 확산할 때 해당 지점이 확산되는 지점일 수 있기 때문이다.

 

그래서 바로 while문을 종료하는게  아니라 불을 확산시킨 후, 후보지점들이 불에의해 영향을 받은게 아니면 탈출할 수 있다고 판단한다.