알고리즘 문제풀이/백준

[백준 17142번] 연구소 3

슥지니 2022. 3. 30. 15:31
반응형

문제 링크: https://www.acmicpc.net/problem/17142

 

17142번: 연구소 3

인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 바이러스는 활성 상태와 비활성 상태가 있다. 가장 처음에 모든 바이러스는 비활성 상태이고

www.acmicpc.net

<문제 풀이> 조합, BFS
이 문제는 두 가지만 조심하면 되는데

 

첫 번째는 "활성 바이러스로 인해 비활성 바이러스가 활성 바이러스로 바뀔 때 0초가 걸린다"입니다.

이 경우에는 활성 바이러스를 기준으로 BFS를 하다가 비활성 바이러스를 만나면 따로 바이러스라고 체크해주고 나중에 걸린 시간을 갱신할 때 이 부분은 스킵하면 됩니다.

 

두 번째는 조합 알고리즘입니다.

10Cm의 조합 알고리즘을 작성해야 하는데 실수로 틀린 알고리즘을 작성해서 시간이 더 오래 걸릴 수도 있습니다.

아래 문제를 풀어보시면 도움이 됩니다.

[조합 문제]
https://www.acmicpc.net/problem/15663

 

15663번: N과 M (9)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

 

 

<C++ 소스 코드>

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
#include<iostream>
#include<vector>
#include<utility>
#include<algorithm>
#include<queue>
using namespace std;
 
#define WALL 1
#define VIRUS 2
#define ACTIVE 0
#define INACTIVE -1
#define EMPTY -2
#define INIT 99999999
#define X first
#define Y second
 
const int dx[4= { 001-1 };
const int dy[4= { 1-100 };
 
int N, M;
int board[50][50];
int visited[50][50];
bool existVirus[50][50];
vector<pair<intint> > virus;
int virus_size;
pair<intint> selected[10];
bool isCheck[10];
int res = -1;
int emptyCnt;
int solve(int idx, int depth) {
    int ret = INIT;
    if (depth == M) {
        fill(&visited[0][0], &visited[49][50], EMPTY);
        fill(&existVirus[0][0], &existVirus[49][50], false);
        queue<pair<intint> > Q;
        for (int i = 0; i < M; i++) {
            auto e = selected[i];
            visited[e.X][e.Y] = ACTIVE;
            Q.push({ e.X, e.Y });
        }
        for (auto e : virus) {
            if (visited[e.X][e.Y] == EMPTY) visited[e.X][e.Y] = INACTIVE;
        }
        int cnt = 0;
        while (!Q.empty()) {
            auto cur = Q.front(); Q.pop();
            for (int dir = 0; dir < 4; dir++) {
                int nx = cur.X + dx[dir];
                int ny = cur.Y + dy[dir];
                if (nx < 0 || ny < 0 || nx >= N || ny >= N)continue;
                if (board[nx][ny] == WALL) continue;
            
                if (visited[nx][ny] == EMPTY) {
                    Q.push({ nx, ny });
                    visited[nx][ny] = visited[cur.X][cur.Y] + 1;
                }
                else if (visited[nx][ny] == INACTIVE) {
                    existVirus[nx][ny] = true;
                    Q.push({ nx, ny });
                    visited[nx][ny] = visited[cur.X][cur.Y] + 1;
                }
            }
        }
        
        int temp = -1;
        bool flag = false;
        for (int i = 0; i < N; i++) {
            if (flag) break;
            for (int j = 0; j < N; j++) {
                if (board[i][j] == WALL)continue;
                if (existVirus[i][j] == truecontinue;
                if (visited[i][j] == EMPTY) {
                    temp = INIT;
                    flag = true;
                    break;
                }
                temp = max(temp, visited[i][j]);
            }
        }
        ret = min(ret, temp);
    }
    else {
        for (int i = idx; i < virus_size; i++) {
            if (isCheck[i])continue;
            selected[depth] = virus[i];
            isCheck[i] = true;
            ret = min(ret, solve(i + 1, depth + 1));
            isCheck[i] = false;
        }
        
    }
    return ret;
}
 
int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
 
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cin >> board[i][j];
            if (board[i][j] == VIRUS) virus.push_back({ i, j });
            else if (board[i][j] == 0)emptyCnt++;
        }
    }
    virus_size = virus.size();
    int ret = solve(00);
    if (ret == INIT) cout << -1;
    else cout << ret;
    return 0;
}
cs
반응형